We have inherited a project that is a wrapper around a section of the core business model.
There is one method that takes a generic, finds items matching that type from a member and then returns a list of that type.
public List<T> GetFoos<T>()
{
List<IFoo> matches = Foos.FindAll(
f => f.GetType() == typeof(T)
);
List<T> resultList = new List<T>();
foreach (var match in matches)
{
resultList.Add((T)obj);
}
}
Foos can hold the same object cast into various classes in inheritance hierarchy to aggregate totals differently for different UI presentations. There are 20+ different types of descendants that can be returned by GetFoos.
The existing code basically has a big switch statement copied and pasted throughout the code. The code in each section calls GetFoos with its corresponding type.
We are currently refactoring that into one consolidated area, but as we are doing that we are looking at other ways to work with this method.
One thought was to use reflection to pass in the type, and that worked great until we realized the Invoke returned an object, and that it needed to be cast somehow to the List <T>.
Another was to just use the switch statement until 4.0 and then use the dynamic language options.
We welcome any alternate thoughts on how we can work with this method. I have left the code pretty brief, but if you'd like to know any additional details please just ask.
Update
The switch statement was originally using strings and the first pass was moving it into a Presenter with something like this: (No refactoring done on the switch, just where the data went).
// called on an event handler in FooPresenter
// view is the interface for the ASPX page injected into FooPresenter's constructor
// wrapper is the instance of the model wrapper that has the GetFoos method
// selectedFooName is the value of a DropDownList in the Page
// letting the user say how they want to see the animals
// its either one big group (Animal)
// or individual types (Tiger, Lion)
private void LoadFoos(string selectedFooName)
{
switch (selectedFooName)
{
case "Animal": // abstract base class for all other types
this.view.SetData(this.wrapper.GetFoos<Animal>();
case "Lion":
this.view.SetData(this.wrapper.GetFoos<Lion>();
break;
case "Tiger":
this.view.SetData(this.wrapper.GetFoos<Tiger>();
break;
case "Bear":
this.view.SetData(this.wrapper.GetFoos<Bear>();
break;
}
}
The View implementation (codebehind for an ASPX page)
public void SetData<T>(List<T> data)
{
// there is a multiview on the page that contains user controls with
// grid layouts for the different types
// there is a control for the common type of "Animal"
// and other controls for Tiger, Bear, etc
// the controls contain a 3rd party grid of pain
// and the grids' binding event handlers cast the data item
// for the row and do some stuff with it specific to that type
}
Our first pass was going to be at least using the Type in the switch statement, or adding an enum.
I played around with using the Strategy Pattern but had to stop when I got to the loading factory returning the List again and realizing I didn't have the type.
It's difficult without seeing the code calling GetFoos()... If you can show more code describing how this is being called, we can suggest how to refactor that.
It sounds like the solution is to make your calling routine a generic routine as well - so that it can avoid the "switch" around the 20 types by just using a single generic type, specified as needed. However, this may not be feasable, but again, without code, it's difficult to know...
That being said, you can refactor GetFoos to be much simpler:
public List<T> GetFoos<T>()
{
return Foos.OfType<T>().ToList();
}
Edit: As Eric Lippert points out, the above code returns any type that is a type of T, but also subclasses of T. Although this is most likely the behavior that would actually be desired, it is different than the original code. If this is not desirable for some reason, you could, instead, use:
public List<T> GetFoos<T>()
{
Type type = typeof(T);
return Foos.Where(item => item.GetType() == type).ToList();
}
This will have the same behavior as the original code.
Something like this?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
namespace SO_2480770 {
interface IFoo {}
class MyBase : IFoo {}
class Bar : MyBase {}
class Program {
IEnumerable<IFoo> Foos { get; set; }
static void Main(string[] args) {
List<MyBase> bases = new List<MyBase>() { new MyBase(), new MyBase() };
List<Bar> bars = new List<Bar>() { new Bar(), new Bar() };
Program p = new Program();
p.Foos = bases.Concat(bars);
var barsFromFoos = p.GetFoos<Bar>();
var basesFromFoos = p.GetFoos<MyBase>();
Debug.Assert(barsFromFoos.SequenceEqual(bars));
Debug.Assert(basesFromFoos.SequenceEqual(bases.Concat(bars)));
Debug.Assert(!barsFromFoos.SequenceEqual(bases));
Console.ReadLine();
}
public List<T> GetFoos<T>() where T : IFoo {
return Foos.OfType<T>().ToList();
}
}
}
To get rid of big switch statements, you either have to push the generics futher up. I.E. make the method that has the switch statement take a generic type parameter, and keep going until you can't go any futher, if you have to, up the calling chain. When that gets too difficult, think about design patterns such as abstract factory, factory, template methods etc.... It depends on how complex the calling code is.
Related
I defined the following class:
public abstract class AbstractPackageCall
{
...
}
I also define a subclass of this class:
class PackageCall : AbstractPackageCall
{
...
}
There are also several other subclases of AbstractPackageCall
Now I want to make the following call:
List<AbstractPackageCall> calls = package.getCalls();
But I always get this exception:
Error 13 Cannot implicitly convert type 'System.Collections.Generic.List<Prototype_Concept_2.model.PackageCall>' to 'System.Collections.Generic.List<Prototype_Concept_2.model.AbstractPackageCall>'
What is the problem here? This is the method Package#getCalls
internal List<PackageCall> getCalls()
{
return calls;
}
The simplest way to understand why this is not allowed is the following example:
abstract class Fruit
{
}
class Apple : Fruit
{
}
class Banana : Fruit
{
}
// This should intuitively compile right? Cause an Apple is Fruit.
List<Fruit> fruits = new List<Apple>();
// But what if I do this? Adding a Banana to a list of Apples
fruits.Add(new Banana());
The last statement would ruin the type safety of .NET.
Arrays however, do allow this:
Fruit[] fruits = new Apple[10]; // This is perfectly fine
However, putting a Banana into fruits would still break type safety, so therefor .NET has to do a type check on every array insertion and throw an exception if it's not actually an Apple. This is potentially a (small) performance hit, but this can be circumvented by creating a struct wrapper around either type as this check does not happen for value types (because they can't inherit from anything). At first, I didn't understand why this decision was made, but you'll encounter quite often why this can be useful. Most common is String.Format, which takes params object[] and any array can be passed into this.
In .NET 4 though, there's type safe covariance/contravariance, which allows you to make some assignments like these, but only if they're provably safe. What's provably safe?
IEnumerable<Fruit> fruits = new List<Apple>();
The above works in .NET 4, because IEnumerable<T> became IEnumerable<out T>. The out means that T can only ever come out of fruits and that there's no method at all on IEnumerable<out T> that ever takes T as a parameter, so you can never incorrectly pass a Banana into IEnumerable<Fruit>.
Contravariance is much the same but I always forget the exact details on it. Unsurprisingly, for that there's now the in keyword on type parameters.
Now if you want to make the following call:
List<PackageCall> calls = package.getCalls();
// select only AbstractPackageCall items
List<AbstractPackageCall> calls = calls.Select();
calls.Add(new AnotherPackageCall());
I call this generalization.
Also, you can use this more specific:
List<PackageCall> calls = package.getCalls();
// select only AnotherPackageCall items
List<AnotherPackageCall> calls = calls.Select();
calls.Add(new AnotherPackageCall());
Implement this using extension method:
public static class AbstractPackageCallHelper
{
public static List<U> Select(this List<T> source)
where T : AbstractPackageCall
where U : T
{
List<U> target = new List<U>();
foreach(var element in source)
{
if (element is U)
{
target.Add((U)element);
}
}
return target;
}
}
Why what you try does't work
You are asking the compiler to treat a List<PackageCall> as a List<AbstractPackageCall>, which it is not. It's another matter that each of those PackageCall instances is in fact an AbstractPackageCall.
What would work instead
var calls = package.getCalls().Cast<AbstractPackageCall>().ToList();
Why what you try will never be allowed to work
Even though each item inside the return value of package.getCalls() derives from AbstractPackageCall, we can't treat the whole list as List<AbstractPackageCall>. Here's what would happen if we could:
var calls = package.getCalls(); // calls is List<PackageCall>
List<AbstractPackageCalls> apcs = calls; // ILLEGAL, but assume we could do it
apcs.Add(SomeOtherConcretePackageCall()); // BOOM!
If we could do that, then we could add a SomeOtherConcretePackageCall to a List<PackageCall>.
Because List<PackageCall> does not inherit from List<AbstractPackageCall>. You can use the Cast<>() extension method, like:
var calls = package.getCalls().Cast<AbstractPackageCall>();
You cannot perform this conversion, because a List<AbstractPackageCall> can contain anything that derives from AbstractPackageCall, while a List<PackageCall> cannot -- it can only contain things that derive from PackageCall.
Consider if this cast were allowed:
class AnotherPackageCall : AbstractPackageCall { }
// ...
List<AbstractPackageCall> calls = package.getCalls();
calls.Add(new AnotherPackageCall());
You just added an AnotherPackageCall into a List<PackageCall> -- but AnotherPackageCall does not derive from PackageCall! That's why this conversion is not allowed.
Problem: I have 2 types which are result sets of 2 different procedures in DB:
Proc1Result, Proc2Result (We had to split them - but they are basically the same as comes for input/output)
I then decided that I could make use of an interface to switch between needed procedures on runtime - but this means I would need 1 common type to which i could convert Proc1Result and Proc2Result
Just so I do not need to maintain this new class (create all the properties, add/remove if anything changes in DB result) - I derived this class from one of the results:
public class DerivedClassForInterface : Proc1Result {}
Then I implemented explicit cast from the 2nd proc which works fine, but when I want to implement explicit cast from base class to derived class - it wont allow me (since it kinda already "does" - but it fails at runtime):
public class DerivedClassForInterface : Proc1Result
{
//ok - and works as expected
public static explicit operator DerivedClassForInterface(Proc2Result v)
{
return new DerivedClassForInterface
{
...
};
}
//fail: 'user-defined' conversations to or from a base class are not allowed
public static explicit operator DerivedClassForInterface(Proc1Result v)
{
return new DerivedClassForInterface
{
...
};
}
}
so this works:
//result2 is of type Proc1Result
DerivedClassForInterface castedResult = (DerivedClassForInterface)result2;
//compiles - works as expected at runtime
but this does not:
//result1 is of type Proc1Result
DerivedClassForInterface castedResult = (DerivedClassForInterface)result1;
//compiles - conversation fails at runtime
So why I can not write my own explicit operator if you can not cast from base class to derived class?
Interesting that compiler allows me to cast from base to derived class, and yet it does not work at runtime.
Probably I will go just for simple functions which will do the "casting" for me. Anyone can suggest a better solution (keep in mind that I would like to keep "DerivedClassForInterface" to obey changes in "Proc1Result" (or "Proc2Result" - doesn't matter))
EDIT
#Peter Duniho - Here the types "Proc1Result" and "Proc2Result" are generated as results from stored procedures (linq2sql). I would like to have a code which I wont need to touch when output of those procedures change (since there are bunch of procedures we need to segment - and implementing new modules could and often does add more output).
Proc1 and Proc2 are basically same stored procedures (they require exactly the same input and provides same output (type-wise not data-wise)). Both of them work with different segments of data and are required to be separate.
Sorry for making this confusing (was at end of my working day...) and not clarifying - the question here actually is:
Why compiler lets me cast from base to derived class when runtime causes exception? And why I can not implement this casting myself (... because it kinda already does - but it just does not work at runtime?)
So from where I stand - it looks the following:
- I can not implement this cast because it already exists
- Yet it is doomed to not work
Here is "Minimal, Complete, and Verifiable code example" (thanks for the link):
//results from stored procedures in database which got splitted appart (linq 2 sql)
class Proc1Result { }
class Proc2Result { }
//
class DerivedClassForInterface : Proc1Result
{
public static explicit operator DerivedClassForInterface(Proc2Result v)
{
//this part would be exported in generic function
var derivedClassInstance = new DerivedClassForInterface();
var properties = v.GetType().GetProperties();
foreach (var property in properties)
{
var propToSet = derivedClassInstance.GetType().GetProperty(property.Name);
if (propToSet.SetMethod != null) propToSet.SetValue(derivedClassInstance, property.GetValue(v));
}
return derivedClassInstance;
}
}
interface IProcLauncher
{
DerivedClassForInterface GetNeededData();
}
class ProcLauncher1 : IProcLauncher
{
public DerivedClassForInterface GetNeededData()
{
var dataFromDb = new Proc1Result();/*just ilustrative*/
return (DerivedClassForInterface)dataFromDb;
}
}
class ProcLauncher2 : IProcLauncher
{
public DerivedClassForInterface GetNeededData()
{
var dataFromDb = new Proc2Result();/*just ilustrative*/
return (DerivedClassForInterface)dataFromDb;
}
}
class Program
{
static void Main(string[] args)
{
bool causeInvalidCastException = true;
IProcLauncher procedureLauncher;
if (causeInvalidCastException) procedureLauncher = new ProcLauncher1();
else procedureLauncher = new ProcLauncher2();
var result = procedureLauncher.GetNeededData();
Console.WriteLine("I got here!");
}
}
The idea was:
- Not have to change any code if output of procedures change.
- Decide at runtime which proc to use.
- Export the convertation part as generic function.
- Got to be injectable.
I can solve this - let say - by just 1 generic function which will handle conversation for all cases, but the question is above in bold.
I implemented the converting the following way:
class BaseConverter
{
protected T Convert<T, X>(X result)
{
var derivedClassInstance = Activator.CreateInstance<T>();
var derivedType = derivedClassInstance.GetType();
var properties = result.GetType().GetProperties();
foreach (var property in properties)
{
var propToSet = derivedType.GetProperty(property.Name);
if (propToSet.SetMethod != null)
{
propToSet.SetValue(derivedClassInstance, property.GetValue(result));
}
}
return derivedClassInstance;
}
protected List<T> Convert<T, X>(List<X> listResult)
{
var derivedList = new List<T>();
foreach (var r in listResult)
{
//can cope with this - since there will not ever be many iterations
derivedList.Add(Convert<T, X>(r));
}
return derivedList;
}
}
So interface implementation classes would inherit from it:
class ProcLauncher2 : BaseConverter, IProcLauncher
{
public DerivedClassForInterface GetNeededData()
{
var dataFromDb = new Proc2Result();/*just ilustrative*/
//usage (works for single result or list if I need a list returned):
return Convert<DerivedClassForInterface, Proc2Result>(dataFromDb);
}
//other methods...
}
Yet - it is not clear for me - why there is already cast from base class to derived - if that does not work. Imo - it should not be there and throw error at compile time.
I don't understand your question very well. You seem to say that the compiler lets you write the code you posted, but that it fails at runtime. This isn't my experience. I get a compile-time error on the explicit conversion operation for the base class:
error CS0553: 'Derived.explicit operator Derived(Base1)': user-defined conversions to or from a base class are not allowed
Seems pretty clear to me. As for why you aren't allowed to write code like that, you'd have to ask the language designers to know for sure, but it seems like a reasonable restriction to me. There already is a safe, built-in conversion from any base class to a derived class of that base class, as long as the base class instance is in fact an instance of the derived class. It would be confusing and likely to lead to bugs if programmers were allowed to make additional conversions, never mind greatly complicate the language specification's rules for the casting/conversion operator.
As for the broader problem, I don't understand the approach you've chosen. You're designing the classes exactly upside-down from the way one would normally do this. If you have a number of classes that all have shared members, you want to be able to treat all those classes as the same in some context, and you want to be able to implement those shared members exactly once and share them among the other classes, you would put all those members in a single base class, and then derive all your various types from that class.
I don't even see how your current approach addresses this concern:
Just so I do not need to maintain this new class (create all the properties, add/remove if anything changes in DB result)
Since Proc2Result doesn't inherit Proc1Result, if Proc1Result changes, you'll have to go change Proc2Result to match anyway. And any other similar types. And the DerivedClassForInterface class. And you have to change all the explicit operators. How is that better?
I would think you would prefer something like:
class BaseClassForInterface
{
// declare all shared members here
}
class Proc1Result : BaseClassForInterface { ... }
class Proc2Result : BaseClassForInterface { ... }
Then, for each new Proc...Result class, you simply inherit the base class, no need to re-write the members, and the conversion from each Proc...Result class is trivial. You don't even need to use the casting/conversion operator; the language already knows how to implicitly convert from derived classes to base classes, because the derived classes are the base classes.
This is, in fact, the standard way to use OOP. It's one of the most fundamental features of any OOP language.
If that doesn't get you back on track, you'll need to improve the question, so that it's more clear what you are doing and why. You'll also need to provide a good Minimal, Complete, and Verifiable code example that clearly illustrates your question, explaining precisely what that code does and what you want it to do instead.
Addendum:
Thanks for the edit. Your question is a lot more specific and clear now. I still have questions, but at least I understand the real context.
It seems to me that you already understand most of the basic answer to your question:
Why compiler lets me cast from base to derived class when runtime causes exception? And why I can not implement this casting myself (... because it kinda already does - but it just does not work at runtime?)
So from where I stand - it looks the following:
- I can not implement this cast because it already exists
- Yet it is doomed to not work
I.e. yes, I believe the language disallows this because there is already a built-in cast, and yes the exact approach you seek is doomed to not work.
As far as this part goes:
The idea was:
- Not have to change any code if output of procedures change.
- Decide at runtime which proc to use.
- Export the convertation part as generic function.
- Got to be injectable.
If I understand the first point, this is why you inherit one of the stored procedure types. So that you get the property declarations for free. Seems a little hacky to me, but I admit I do understand the motivation.
As I understand the third point above and your statement after in your post, you already know how you can write a generic method to do the conversion. E.g. something like:
DerivedClassForInterface ConvertToClassForInterface<T>(T t)
{
DerivedClassForInterface result = new DerivedClassForInterface();
Type resultType = typeof(DerivedClassForInterface);
PropertyInfo[] properties = typeof(T).GetProperties();
foreach (var property in properties)
{
var propToSet = resultType.GetProperty(property.Name);
if (propToSet.SetMethod != null)
{
propToSet.SetValue(result, property.GetValue(t));
}
}
return result;
}
I.e. essentially the code you show in your explicit operator (with some minor cleanup/optimization). Or maybe you aren't using the term "generic" literally, and just mean "general purpose". Obviously there's very little in the above that really benefits from the method being generic; you could just as easily use GetType() on the parameter, just as your explicit operator does.
Unfortunately, I don't know how the criteria "Got to be injectable" fits in here. Injectable, how? Do you mean you want to inject the code somewhere else? Or do you mean that the code needs to be compatible with an AOP system, or some other form of code injection applied to it?
Ignoring that part, which I don't understand, I would actually just leverage the compiler and runtime to do all the heavy lifting for me (including caching the reflection stuff, which in your code is going to be very slow). You could write a class like this:
class Wrapper
{
private dynamic _data;
public string Value { get { return _data.Value; } }
public Wrapper(dynamic data)
{
_data = data;
}
}
Given a couple of other classes like this:
class Result1
{
public string Value { get; set; }
}
class Result2
{
public string Value { get; set; }
}
Then you can use it like this:
Result1 r1 = new Result1 { Value = "result 1" };
Result2 r2 = new Result2 { Value = "result 2" };
Wrapper w1 = new Wrapper(r1), w2 = new Wrapper(r2);
Console.WriteLine("w1 result: " + w1.Value);
Console.WriteLine("w2 result: " + w2.Value);
I.e. just create an instance of Wrapper, passing the relevant object (in your case, this would be the generated type's from the stored procedure). The downside is, of course, that you do have to add properties to the Wrapper type to match your stored procedure. But I'm not convinced that's a bad thing. Even if you've somehow arranged it so that none of the rest of the code has to change, it's a relatively minor maintenance task.
And I suspect that altering the stored procedure requires changes elsewhere in the code anyway, to explicitly refer to the properties. Because after all, if the rest of the code is similarly completely agnostic regarding the specific class members (i.e. uses reflection all the way), then you could just pass the result objects around as object types, and not worry about the wrapper at all.
I have an abstract base class P. I have two classes that inherit P called I and O.
I have a Get() method in my repository that returns P. This method always returns an instance of either I or O depending on a value.
public P Get(string pci)
{
var a = GetAByPCI(string pci);
if(a == 1)
return new I();
else if(a == 2)
return new O();
else
// throw exception here.
}
When I call this method from another location I need to check and cast the type.
P p = PRepository.Get("200");
if(p is I)
I i = (I)p;
I'd like to avoid having to check and downcast every time p above is used. I feel as though I'm doing some fundamentally wrong here, but am not certain.
Update:
The derived types I & O have additional properties that need to be used but only pertain to that specific type. P has many abstract properties that are implemented in inheriting types. Downcasting is the only way I can get to the concrete types as needed?
Maybe the logic is entirely wrong.
The whole point of having a base class is to avoid having to deal with the subclass itself. Just add an abstract method to the base class and have it implemented in the sub-classes. This way, the calling code will simply call the method without having to do any casts. This is basic polymorphism.
What is your intention? It seems you are not making proper use of inheritance.
If you return a P object from your methods, you either need to downcast or return the derived types.
You are correct to be suspect of down casting.
I would look at the template method design pattern. If you have a base class it should be used to hide the details of the subclass.
So maybe you have a method in your base class called Execute(). Inside the base class the execute method calls some protected methods, lets say Method1(), and Method2(). Method 1 would contain the shared code, method two would be abstract and the child classes would have to execute it. Then when you get your instance back you just call Execute. The proper Method2() will run without you having to cast downward.
public abstract class MyBaseClass
{
public void DoSomething()
{
//Here's a bunch of stuff I have to do everytime
DoSomethingTypeSpecific();
//I could do more stuff if I needed to
}
protected abstract void DoSomethingTypeSpecific();
}
class MyBaseClassOne : MyBaseClass
{
protected override void DoSomethingTypeSpecific()
{
Console.WriteLine(1);
}
}
class MyBaseClassTwo : MyBaseClass
{
protected override void DoSomethingTypeSpecific()
{
Console.WriteLine(2);
}
}
I would also think about using the Decorator pattern and composition instead of using inheritance.
Nevertheless you still need a cast if you want to access the properties that are not part of the base class.
If all above solutions not fitting your requirements and you don't want to change the base class (adding properties from derrived classes) then you should also think not only about your inheritance design as mentioned by most comments... you should also look for your factory/repository implementation. Is this repository doing the thing you need? Why not add a GetI() and GetO()?
For eample Linq allows you to query and filter a List with using .OfType and you get only elements of Type T.
You can add a specific Get Method with type info (e.g. with generics as I did in my example) and an additional condition.
public T Get<T>(string pci, int c)
{
var a = GetAByPCI(string pci);
if(a == c)
return new T();
else
// throw exception here.
}
Call the method Get with the generic param. The problem of this solution here is that you need to know the condition at the call time and this does not handle "special constructions" (e.g. constructor with params for T). Anyway this could be solved with the factory pattern, too.
I i = PRepository<I>.Get(1, "200"); // create a new I(), only if 1 fits GetAByPCI()
O o = PRepository<O>.Get(2, "123"); // create a new O(), only if 2 fits GetAByPCI()
// can do anything with the concrete type
You could also move the condition out of the repository/factory call with the strategy pattern (already mentioned in my answer above).
It is also possible to wrap up the "as" behind the generic method (I show you how even if I would not recommend it in most cases).
public T Get<T>(string pci)
{
return this.Get(pci) as T; // your method with trying to cast to concrete type
}
This way you can get the implementation as follows:
I i = PRepository<I>.Get("200");
if (i != null)
{
// do I specific tasks
}
It is not possible to eleminate the cast without putting the properties into the base class but you can use the strategy pattern to decouple the object creation (see my question and answer here for an example how to do this). The example shows how to decouple the switch-case but you can do the same thing with the strategy pattern for analysing the result of the context, so you can hide the cast.
public static class A
{
// please note: some example in related to your question
// and the strategy pattern provided at the link
public static P GetI(int a)
{
if (a == 1)
return new I();
else
return null; // <- this is important for evaluation
}
// can put this method anywhere else, also into another class
public static P GetO(int a)
{
if (a == 2)
return new O();
else
return null; // <- this is important for evaluation
}
public static bool Condition(string pci)
{
return !string.IsNullOrEmpty(pci); // could eval different states, values
}
}
Then it is possible to divide the as/is logic into separate methods/classes and the calling class (e.g. controller, client) doesn't need to know all the different specializations.
The following code shows how to create the context. See my posting here for the implementation details of Strategy and Context class.
var strategyI = new Strategy<int, P>(A.Condition, A.GetI);
var strategyO = new Strategy<int, P>(A.Condition, A.GetO);
var strategies = new List<Strategy<int, P>> {strategyI, strategyO};
var context = new Context<int, P>(strategies.ToArray());
var result = context.Evaluate(1); // should return a new I(), with 2 as param a new O()
// once you get the result you can create a new context to work with the result
var strategyWorkI = new Strategy<P, P>(Condition, WorkWithI);
var stragegiesForWork = new List<Strategy<P, P>> {strategyWorkI} // could be more than one
var workContext = new Context<P, P>(strategiesForWork.ToArray());
var p = workContext.Evaluate(result); // does the right thing, but
// no need to know class I here (only P)
if (p == null)
// seems to be something went wrong, throw? ...
And here is the decoupling for the cast but you still need a cast at this point.
public static P WorkWithI(P p)
{
var i = p as I; // I would prefer as instead of is (see boxing/unboxing in .net)
if (i != null)
{
// do what you want with concrete class I in i
}
return i; // <- this is important for Evaluation
}
Anyway... there is still Point in the code with an is/as, but it does not influence your controller / manager etc. (keeps code flexible and pluggable, e.g. via Dependency Injection)
... I can provide a full example if you can't understand my short description.
I'm creating a framework that contains a wrapper around a library (specifically SharpBrake) that performs all interaction with SharpBrake via reflection so there's no hard dependency on the library to 3rd parties of my framework.
If 3rd parties of my framework wants to use SharpBrake, they can just stuff the SharpBrake.dll into the bin folder, but if they don't, they can just forget about it. If my framework had explicit references to SharpBrake types, users of my framework would get exceptions during runtime of SharpBrake.dll missing, which I don't want.
So, my wrapper first loads SharpBrake.dll from disk, finds the AirbrakeClient type, and stores a delegate pointing to the AirbrakeClient.Send(AirbrakeNotice) method in a private field. My problem, however, is that since the Send() method takes an AirbrakeNotice object and I can't reference the AirbrakeNotice object directly, I need to somehow convert the Send() method to an Action<object>.
I have a strong feeling this isn't possible, but I want to explore all options before settling on exposing Delegate and using DynamicInvoke(), which I assume is far from optimal, performance-wise. What I would love to do is the following:
Type clientType = exportedTypes.FirstOrDefault(type => type.Name == "AirbrakeClient");
Type noticeType = exportedTypes.FirstOrDefault(type => type.Name == "AirbrakeNotice");
MethodInfo sendMethod = clientType.GetMethod("Send", new[] { noticeType });
object client = Activator.CreateInstance(clientType);
Type actionType = Expression.GetActionType(noticeType);
Delegate sendMethodDelegate = Delegate.CreateDelegate(actionType, client, sendMethod);
// This fails with an InvalidCastException:
Action<object> sendAction = (Action<object>)sendMethodDelegate;
However, this fails with the following exception:
System.InvalidCastException: Unable to cast object of type 'System.Action`1[SharpBrake.Serialization.AirbrakeNotice]' to type 'System.Action`1[System.Object]'.
Obviously, because sendMethodDelegate is an Action<AirbrakeNotice> and not an Action<object>. Since I can't mention AirbrakeNotice in my code, I'm forced to do this:
Action<object> sendAction = x => sendMethodDelegate.DynamicInvoke(x);
or just exposing the Delegate sendMethodDelegate directly. Is this possible? I know that there's chance of getting into situations where the object can be of a different type than AirbrakeNotice which would be bad, but seeing how much you can mess up with reflection anyway, I'm hoping there's a loophole somewhere.
If you're happy to use expression trees, it's reasonably simple:
ConstantExpression target = Expression.Constant(client, clientType);
ParameterExpression parameter = Expression.Parameter(typeof(object), "x");
Expression converted = Expression.Convert(parameter, noticeType);
Expression call = Expression.Call(target, sendMethod, converted);
Action<object> action = Expression.Lambda<Action<object>>(call, parameter)
.Compile();
I think that's what you want...
If you don't need below C# 4 support you can get much greater performance using the dynamic vs DynamicInvoke.
Action<dynamic> sendAction = x => sendMethodDelegate(x);
Actually I guess you wouldn't even need the above if you can use dynamic, because it would increase performance and simplify everything if you just did:
Type clientType = exportedTypes.FirstOrDefault(type => type.Name == "AirbrakeClient");
dynamic client = Activator.CreateInstance(clientType);
...
client.Send(anAirbrakeNotice);
But if you need to support .net 3.5 jon skeets answer with expression trees is definitely the way to go.
From my comment on the OP:
I'd avoid extended use of reflections if you are concerned about performance. If you can come up with an interface for the class(es) you are using, then I'd create one. Then write a wrapper that implements the interface by calling into the SharpBreak code, and stuff it in a separate DLL. Then dynamically load just your wrapper assembly and concrete wrapper type(s), and call into that interface. Then you don't have to do reflections at a method level.
I'm not sure all the classes you'd need, but here's a simple example of how you can hook into that library with loose coupling based on interfaces.
In your program's assembly:
public IExtensions
{
void SendToAirbrake(Exception exception);
}
public static AirbreakExtensions
{
private static IExtensions _impl;
static()
{
impl = new NullExtensions();
// Todo: Load if available here
}
public static void SendToAirbrake(this Exception exception)
{
_impl.SendToAirbrake(exception);
}
}
internal class NullExtensions : IExtensions // no-op fake
{
void SendToAirbrake(Exception exception)
{
}
}
In a load-if-available (via reflections) assembly
public ExtensionsAdapter : IExtensions
{
void SendToAirbrake(Exception exception)
{
SharpBrake.Extensions.SendToAirbrake(exception);
}
}
The advantage of this approach is that you only use reflections once (on load), and never touch it again. It is also simple to modify to use dependency injection, or mock objects (for testing).
Edit:
For other types it will take a bit more work.
You might need to use the Abstract Factory pattern to instantiate an AirbrakeNoticeBuilder, since you need to deal directly with the interface, and can't put constructors in interfaces.
public interface IAirbrakeNoticeBuilderFactory
{
IAirbrakeNoticeBuilder Create();
IAirbrakeNoticeBuilder Create(AirbrakeConfiguration configuration);
}
If you're dealing with custom Airbreak structures, you'll have even more work.
E.g. for the AirbrakeNoticeBuilder you will have to create duplicate POCO types for any related classes that you use.
public interface IAirbrakeNoticeBuilder
{
AirbrakeNotice Notice(Exception exception);
}
Since you're returning AirbrakeNotice, you might have to pull in nearly every POCO under the Serialization folder, depending on how much you use, and how much you pass back to the framework.
If you decide to copy the POCO code, including the whole object tree, you could look into using AutoMapper to convert to and from your POCO copies.
Alternately, if you don't use the values in the classes you're getting back, and just pass them back to the SharpBreak code, you could come up with some sort of opaque reference scheme that will use a dictionary of your opaque reference type to the actual POCO type. Then you don't have to copy the whole POCO object tree into your code, and you don't need to take as much runtime overhead to map the object trees back and forth:
public class AirbrakeNotice
{
// Note there is no implementation
}
internal class AirbreakNoticeMap
{
static AirbreakNoticeMap()
{
Map = new Dictionary<AirbreakNotice, SharpBreak.AirbreakNotice>();
}
public static Dictionary<AirbreakNotice, SharpBreak.AirbreakNotice> Map { get; }
}
public interface IAirbrakeClient
{
void Send(AirbrakeNotice notice);
// ...
}
internal class AirbrakeClientWrapper : IAirbrakeClient
{
private AirbrakeClient _airbrakeClient;
public void Send(AirbrakeNotice notice)
{
SharpBreak.AirbrakeNotice actualNotice = AirbreakNoticeMap.Map[notice];
_airbrakeClient.Send(actualNotice);
}
// ...
}
internal class AirbrakeNoticeBuilderWrapper : IAirbrakeNoticeBuilder
{
AirbrakeNoticeBuilder _airbrakeNoticeBuilder;
public AirbrakeNotice Notice(Exception exception)
{
SharpBreak.AirbrakeNotice actualNotice =
_airbrakeNoticeBuilder.Notice(exception);
AirbrakeNotice result = new AirbrakeNotice();
AirbreakNoticeMap.Map[result] = actualNotice;
return result;
}
// ...
}
Keep in mind that you only need to wrap the classes and parts of the public interface that you're going to use. The object will still behave the same internally, even if you don't wrap its entire public interface. This might mean you have to do less work, so think hard and try to wrap only what you need now, and what you know you're going to need in the future. Keep YAGNI in mind.
The programming style I have come to really like for problems like this is to write as much strongly-typed code as possible, and then hand off the logic from the dynamically-typed code to the strongly-typed code. So I would write your code like this:
//your code which gets types
Type clientType = exportedTypes.FirstOrDefault(type => type.Name == "AirbrakeClient");
Type noticeType = exportedTypes.FirstOrDefault(type => type.Name == "AirbrakeNotice");
//construct my helper object
var makeDelegateHelperType=typeof(MakeDelegateHelper<,>).MakeGenericType(clientType, noticeType);
var makeDelegateHelper=(MakeDelegateHelper)Activator.CreateInstance(makeDelegateHelperType);
//now I am in strongly-typed world again
var sendAction=makeDelegateHelper.MakeSendAction();
And this is the definition of the helper object, which is able to get away with fewer reflectiony calls.
public abstract class MakeDelegateHelper {
public abstract Action<object> MakeSendAction();
}
public class MakeDelegateHelper<TClient,TNotice> : MakeDelegateHelper where TClient : new() {
public override Action<object> MakeSendAction() {
var sendMethod = typeof(TClient).GetMethod("Send", new[] { typeof(TNotice) });
var client=new TClient();
var action=(Action<TNotice>)Delegate.CreateDelegate(typeof(Action<TNotice>), client, sendMethod);
return o => action((TNotice)o);
}
}
UPDATE: this is a duplicate of
Is the StaticFactory in codecampserver a well known pattern?
Edit: Please note that this answer was given before the question was completely changed over in an edit. Because of that, it now refers to things that were only present in the question as originally stated. I beg your pardon for all the "dangling pointers". :-)
Short answer:
With the code you've posted, I don't see an alternative to casting to IFoo<T>. If you don't, the compiler will give a warning (on my machine, at least).
More elaborate answer:
Does your code actually have to be that way? More specifically, do you need the cast in question in the first place?
I assume you are going to call your factory method more or less like this:
var stringFoo = FooFactory.CreateFoo<string>();
You have to provide the template parameter (string in this case) explicitly because it cannot be derived from any method argument (in this case because there aren't actually any at all). Obviously, the factory method will return an IFoo<string>.
Now, since you have to explicitly specify the type at run-time, you could just as well write:
var stringFoo = StringFoo.Create();
and therefore have a factory method inside StringFoo, like this, that unconditionally does the obvious:
public class StringFoo : IFoo<string>
{
...
public static StringFoo Create() // or alternatively, return an IFoo<string>
{
return new StringFoo();
}
}
By applying this pattern to other IFoo<T> implementations too, this will save you the if chain or switch block inside FooFactory.CreateFoo<T>, make your code easier, and get rid of the necessity to cast (which you are concerned about).
Don't get me wrong, I'm aware that factory methods supporting more than one object type are useful in some cases; but it seems in your case it causes more trouble than it's worth.
P.S.: You might find one aspect of some IoC containers interesting. They usually need to be configured, and this encompasses a process where you register concrete types (i.e. implementation classes) for abstract interfaces; for example (here using Autofac):
var builder = new ContainerBuilder();
builder.RegisterType<StringFoo>().As<IFoo<string>>();
Then later, you can request an object instance of an abstract type:
using (var container = builder.Build())
{
var stringFoo = container.Resolve<IFoo<string>>();
...
}
The Resolve method is the interesting part. You provide it with an abstract type, and using the registered types, it will return a concrete object of type StringFoo. Look into it, if it doesn't sound like overkill to you! :-)
Can you describe the problem you are solving with this mechanism? There is most likely a clearer way to approach it.
Edit
And yes, the code smells. You have left room open for any type, except you then constrain it back to a single type, and generate a run-time exception. Why have a type parameter in that case?
You could try something like this...
public static class FooFactory
{
private static readonly Dictionary<Type, Type> FooTypesLookup;
static FooFactory()
{
FooTypesLookup = (from type in typeof(FooFactory).Assembly.GetExportedTypes()
let fooInterface =
type.GetInterfaces().FirstOrDefault(
x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(IFoo<>))
where fooInterface != null
let firstTypeArgument = fooInterface.GetGenericArguments().First()
select new { Type = type, TypeArgument = firstTypeArgument })
.ToDictionary(x => x.TypeArgument, x => x.Type);
}
public static IFoo<T> CreateFoo<T>()
{
var genericArgumentType = typeof(T);
Type closedFooType;
return FooTypesLookup.TryGetValue(genericArgumentType, out closedFooType)
? (IFoo<T>) Activator.CreateInstance(closedFooType)
: null;
}
}
Or better yet, introduce your favorite IoC container (Windsor, structure map, etc) and register all types that implement IFoo in there and then resolve them when needed in place of the Activator.CreateInstance call.