I am looking for a c# equivelent of my code for a pluggable factory. The advantage of the linked method is that static initialization result in a push operation, where each plugin adds itself to the factory.
C++ code for a pluggable factory: (http://codepad.org/7pgzaaAK)
// base class for plugins
class Foo{
public:
virtual std::string getName()const=0;
virtual void exercise()const=0;
};
// plugin factory
class FooFactory{
public:
static Foo* GetA(std::string s);
typedef std::map<std::string,Foo*(*)(void)> mapType;
static mapType& getA();
};
FooFactory::mapType& FooFactory::getA(){static mapType getA;return getA;}
Foo* FooFactory::GetA(std::string s)
{return getA().find(s)!=getA().end()?getA()[s]():0;} // to simplify access
// helper function to add the fun
template<typename T>
Foo* getNew(){ return new T; }
// use the CRTP to automatically register the object with the factory.
template <typename T> struct Reg { Reg() { /*cout << "registering a " << T().getName( <<endl;*/
FooFactory::getA().insert(std::pair<std::string, Foo*(*)()>(T().getName(), &getNew<T>));} };
template <typename T>
class Foo_reg:public Foo{
public:
Foo_reg(){®}; // using a reff to the static is enough to force initialization of the static earlier
static Reg<T> reg;
};
template <typename T> Reg<T> Foo_reg<T>::reg;
/////////////////
class FooBar:public Foo_reg<FooBar>{ // automatic registration with the factory
public:
FooBar(){a=10;}
virtual std::string getName()const{return "Foo Bar";}
virtual void exercise()const {cout <<a;}
private:
int a;
};
// exercise the factory and objects.
int main(){
Foo* foo=FooFactory::GetA("Foo Bar");
foo->exercise();
}
In C# i can see 2 ways of doing this, both of them pull operations
Have an explicit pre-built list of all plugins, which has to be maintained seperatly from the plugins themselves.
Use code reflection to iterate through all types, checking if they are castable to Foo and initialize their statics, on any dll load and program start.
Is it possible to do this without having to resort to these methods?
I wouldnt worry about reflection to much. Even PEX has no trouble using it. Simply put, by reflection, you're just checking the metadata of an assembly and see if it defined any classes that implement a certain interface or are marked with a certain attribute, this is very fast! Anyways, the CLR will never run code that is not being called explicitly so no, you have to resort to some kind of pulling mechanism (even if you make it look like a push mechanism)
realizing that the only real requiremnt here was that at the end of the day we have a lookup between a type identifier (string/Type) and a function which allows us to get an instance of that type i ended up resolving this with the following pattern:
private static readonly Dictionary<string, KeyValuePair<TConstructor, Node>> Types =
new Dictionary<string, KeyValuePair<TConstructor, Node>>();
private static readonly Dictionary<Type, string> classNameMap = new Dictionary<Type, string>();
private class constructableNode<T> where T : Node, new()
{
public constructableNode()
{
var t = new T();
Types[t.Type()] = new KeyValuePair<TConstructor, Node>(thisTConstructor, t);
classNameMap[typeof (T)] = t.Type();
}
private static T thisTConstructor()
{
var t = new T();
return t;
}
}
public static Node GetA(string s)
{
if (Types.ContainsKey(s) == false)
{
UpdateAvailableTypes();
}
if (Types.ContainsKey(s) == false)
{
throw new BadNodeType(s);
}
// look up the correct constructor, and call it.
return Types[s].Key();
}
public static void UpdateAvailableTypes()
{
Assembly targetAssembly = Assembly.GetExecutingAssembly(); // or whichever - could iterate dlls in the plugins folder or something
UpdateAvailableTypes(targetAssembly);
classNameMap[typeof (Node)] = "BaseNode"; // HARD CODED INTO the node type itself also
}
private static void UpdateAvailableTypes(Assembly targetAssembly)
{
IEnumerable<Type> subtypes = targetAssembly.GetTypes().Where(t => t.IsSubclassOf(typeof (Node)));
Type nodeConstructor = typeof (constructableNode<>);
foreach (Type currentType in subtypes)
{
// this line throwing an error means that the Node type does not have an empty constructor.
Activator.CreateInstance(nodeConstructor.MakeGenericType(currentType));
}
}
This is a simple method, but the cost of the dynamic Invoke each call is a bit steep compared to other options, and when i first used this pattern for the section below, it was 80% of the critical code path runtime.
HOWEVEVER: Due to performance constraints a different pattern of construction was needed for part of my code which was rebuilt quickly (potentially millions of objects, wanted sub-second response time). (see discussion at http://blogs.msdn.com/b/haibo_luo/archive/2005/11/17/494009.aspx for various methods of reflection based construction)
for these i needed the following construction paradigm, whereby the intermediate lookup through the function call to the generic class was washed out
static buildCostItems()
{
//from http://blogs.msdn.com/b/haibo_luo/archive/2005/11/17/494009.aspx
AssemblyBuilder asmBldr = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName("inmemory"),
AssemblyBuilderAccess.Run);
ModuleBuilder modBldr = asmBldr.DefineDynamicModule("helper");
TypeBuilder typeBldr = modBldr.DefineType("ClassFactory");
Type tci = typeof (CostsItem);
IEnumerable<Type> types = Assembly.GetExecutingAssembly().GetTypes().Where(tci.IsAssignableFrom);
//// Note -- assumption of currently executing assembly -- this isn't a requirement, but didn't need the dynamic callback capabilities of the Node constructor here.
List<Type> enumerable = types as List<Type> ?? types.ToList();
foreach (Type type in enumerable)
{
MethodBuilder methBldr = typeBldr.DefineMethod(type.Name,
MethodAttributes.Public | MethodAttributes.Static, type,
new[] {typeof (CostsItem)});
ILGenerator ilgen = methBldr.GetILGenerator();
ilgen.Emit(OpCodes.Nop);
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Newobj, type.GetConstructor(new[] {typeof (CostsItem)}));
ilgen.Emit(OpCodes.Ret);
}
Type baked = typeBldr.CreateType();
foreach (Type type in enumerable)
ctors.Add(type,
(CtorCloneDelegate)
Delegate.CreateDelegate(typeof (CtorCloneDelegate), baked.GetMethod(type.Name)));
}
Related
The question is somewhat related to this: How can I cast a delegate that takes a derived-type argument to a delegate with a base-type argument? but I have a dynamic situation.
So lets say I have two classes:
class Base
{ }
class Derived : Base
{ }
static class Workers
{
public static void DoSomething(Derived obj) { ... }
}
As you can see Workers.DoSomething is Action<Derived> and I want to cast it to Action<Base>. I know this is unsafe but my case is as follows: I keep a dictionary
Dictionary<Type, Action<Base>> actions;
and based on given objects obj.GetType() I retrieve one action and call it. And so I guarantee in my code that such action will be called with an appropriate type.
But those actions depend on the derived type obviously. Now the linked question suggests something like
actions[typeof(Derived)] = (obj) => Workers.DoSomething((Derived)obj);
This is ok in a situation when you know types at compile time. But in my case I retrieve them via reflection. So here's the setup
Type objType; // given
MethodInfo doSomethingMethod; // given, guaranteed to be Action<objType>
actions[objType] = // here what?
So far, surprisingly, the simplest solution I came up with is to create the method dynamically like follows:
Type objType; // given
MethodInfo doSomethingMethod; // given
var dynamicMethod = new DynamicMethod(
$"Dynamic{doSomethingMethod.Name}",
typeof(void),
new Type[] { typeof(Base) },
typeof(Base).Module
);
var il = dynamicMethod.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.EmitCall(OpCodes.Callvirt, doSomethingMethod, null);
il.Emit(OpCodes.Ret);
actions[objType] = (Action<Base>)dynamicMethod
.CreateDelegate(typeof(Action<Base>));
And so I force the call at CIL level. My real code is slightly more complicated since those actions accept two parameters. But that's just noise.
This works (and there's no cast as a bonus). But it looks kind of... I don't know, unsafe. And probably hard to maintain. Is there a better way to solve my problem?
Note: I want to avoid doSomethingMethod.Invoke due to its significant overhead.
Note 2: I have no control over those classes and actions. I can only inspect them.
You seem aware that you are turning the rules of covariance and contravariance upside-down, nevertheless here's something fairly tidy that may work for the situation you describe (you can also check that (b as Derived) != null just to be sure):
class Base { }
class Derived : Base { }
static class Workers
{
public static void DoSomething(Derived obj) { Console.WriteLine("Test"); }
}
class Program
{
static Dictionary<Type, Action<Base>> actions;
// *** Note use of dummy to avoid having to know T at compile time and T : Base constraint
// (compiler can't infer T from Action<T> alone, this way runtime works out T from given object instance)...
static void AddAction<T>(T dummy, Action<T> a) where T : Base
{
actions.Add(typeof(T), b => a(b as T));
}
static void Main(string[] args)
{
actions = new Dictionary<Type, Action<Base>>();
var o = new Derived(); // the object you get "from elsewhere"
AddAction(o, Workers.DoSomething);
actions[o.GetType()](o);
Console.ReadKey();
}
}
Hope this is useful. (Very curious about the "Why?" though ;-)
I can't claim this as my idea, but found it here: https://stackoverflow.com/a/32702091/1848953 while researching your question.
First:
private static Action<object> ConvertDelegateToAction<T>(Delegate d) { return obj => ((Action<T>)d)((T)obj); }
private static readonly MethodInfo CastMethodInfo = typeof(Program).GetMethod(nameof(ConvertDelegateToAction), BindingFlags.Static | BindingFlags.NonPublic);
used:
public static Action<object> GetActionT(Type t, Delegate d) { return (Action<object>)CastMethodInfo.MakeGenericMethod(t).Invoke(null, new object[] { d }); }
Quite tidy I think. You GetType() at runtime and use Invoke() but only to get the Action<object> up-front. (Instead of a base class, I used an empty interface. Seemed to work fine.)
Let us know if this gives satisfaction.
I need to find out a size of a generic structure (I can not do it like sizeof(T) or using Marshal.SizeOf(...) 0> gives me an error)
So I wrote:
public static class HelperMethods
{
static HelperMethods()
{
SizeOfType = createSizeOfFunc();
}
public static int SizeOf<T>()
{
return SizeOfType(typeof(T));
}
public static readonly Func<Type, int> SizeOfType = null;
private static Func<Type, int> createSizeOfFunc()
{
var dm = new DynamicMethod("SizeOfType", typeof(int), new Type[] { typeof(Type) });
ILGenerator il = dm.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Sizeof); //needs to be il.Emit(OpCodes.Sizeof, typeof(something))
il.Emit(OpCodes.Ret);
var func = (Func<Type, int>)dm.CreateDelegate(typeof(Func<Type, int>));
return func;
}
}
A diffuclty is that il.Emit(OpCodes.Sizeof) needs an argument which I can not pass it during the method (SizeOfType) creation. How can I pass a parameter which is on stack to il.Emit(OpCodes.Sizeof) using IL ? (or a different solution but I want to cache a function (delegate) not a result what is proposed in the 2nd answer)
Taking the above thinking one step further, I arrived at:
public static class TypeSize<T>
{
public readonly static int Size;
static TypeSize()
{
var dm = new DynamicMethod("SizeOfType", typeof(int), new Type[] { });
ILGenerator il = dm.GetILGenerator();
il.Emit(OpCodes.Sizeof, typeof(T));
il.Emit(OpCodes.Ret);
Size = (int)dm.Invoke(null, null);
}
}
...which I believe is the most efficient solution to the problem.
Computing size is something that is fraught with problems because you need to know what is meaningful in the context you are using it. I'd assume there is a good reason for Marshal.SizeOf to throw when the argument is a generic struct, but I don't know what it is.
With that caveat, this code seems to work and gives similar results to Marshal.SizeOf for non-generic structs. It generates a new dynamic method that gets the size via the sizeof IL opcode for the type. It then caches the result (since generating a dynamic method is some what expensive) for future use.
public class A { int x,y,z; }
public struct B { int x,y,z,w,a,b; }
public struct C<T> { Guid g; T b,c,d,e,f; }
public class Program
{
public static void Main(string[] args)
{
Console.WriteLine(IntPtr.Size); // on x86 == 4
Console.WriteLine(SizeHelper.SizeOf(typeof(C<double>))); // prints 56 on x86
Console.WriteLine(SizeHelper.SizeOf(typeof(C<int>))); // prints 36 on x86
}
}
static class SizeHelper
{
private static Dictionary<Type, int> sizes = new Dictionary<Type, int>();
public static int SizeOf(Type type)
{
int size;
if (sizes.TryGetValue(type, out size))
{
return size;
}
size = SizeOfType(type);
sizes.Add(type, size);
return size;
}
private static int SizeOfType(Type type)
{
var dm = new DynamicMethod("SizeOfType", typeof(int), new Type[] { });
ILGenerator il = dm.GetILGenerator();
il.Emit(OpCodes.Sizeof, type);
il.Emit(OpCodes.Ret);
return (int)dm.Invoke(null, null);
}
}
Edit
As far as I can tell there is no way to make non-generic delegate that you can cache. The SizeOf opcode requires a metadata token. It does not take a value from the evaluation stack.
Actually the code below works as well. I'm not sure why Marshal.SizeOf(Type) throws an argument exception when the type is generic structure but Marshal.SizeOf(Object) does not.
public static int SizeOf<T>() where T : struct
{
return Marshal.SizeOf(default(T));
}
It would appear that your aim is to resolve the argument Type from your functions return type Func<Type, int> at compile time. This information is not known at compile time and there is no apparent way to resolve this information using reflection at runtime.
I do not see what benefit returning the the dynamic method serves instead of invoking the dynamic method and returning the result immediately. Given that you have not given any context I would propose the obvious solution, return the value immediately. If your concerns lie with performance then simply cache the results in a dictionary.
public static class GlobalExtensions
{
public static int SizeOf<T>()
{
return SizeOf(typeof (T));
}
public static int SizeOf(this Type type)
{
var dynamicMethod = new DynamicMethod("SizeOf", typeof(int), Type.EmptyTypes);
var generator = dynamicMethod.GetILGenerator();
generator.Emit(OpCodes.Sizeof, type);
generator.Emit(OpCodes.Ret);
var function = (Func<int>) dynamicMethod.CreateDelegate(typeof(Func<int>));
return function();
}
}
Using an extension method leverages some nice syntax. You can now proceed to obtain the size of a generic structure or class using the following code:
var size = TypeExtensions.SizeOf<Example<int>>();
//alternative syntax...
size = typeof (Example<int>).SizeOf();
Now there is possibility for the unmanaged types in unsafe context to do this, if that is sufficient.
private unsafe int MySizeOf<T>() where T : unmanaged
{
return sizeof(T);
}
I asked a question yesterday regarding using either reflection or Strategy Pattern for dynamically calling methods.
However, since then I have decided to change the methods into individual classes that implement a common interface. The reason being, each class, whilst bearing some similarities also perform certain methods unique to that class.
I had been using a strategy as such:
switch (method)
{
case "Pivot":
return new Pivot(originalData);
case "GroupBy":
return new GroupBy(originalData);
case "Standard deviation":
return new StandardDeviation(originalData);
case "% phospho PRAS Protein":
return new PhosphoPRASPercentage(originalData);
case "AveragePPPperTreatment":
return new AveragePPPperTreatment(originalData);
case "AvgPPPNControl":
return new AvgPPPNControl(originalData);
case "PercentageInhibition":
return new PercentageInhibition(originalData);
default:
throw new Exception("ERROR: Method " + method + " does not exist.");
}
However, as the number of potential classes grow, I will need to keep adding new ones, thus breaking the closed for modification rule.
Instead, I have used a solution as such:
var test = Activator.CreateInstance(null, "MBDDXDataViews."+ _class);
ICalculation instance = (ICalculation)test.Unwrap();
return instance;
Effectively, the _class parameter is the name of the class passed in at runtime.
Is this a common way to do this, will there be any performance issues with this?
I am fairly new to reflection, so your advice would be welcome.
When using reflection you should ask yourself a couple of questions first, because you may end up in an over-the-top complex solution that's hard to maintain:
Is there a way to solve the problem using genericity or class/interface inheritance?
Can I solve the problem using dynamic invocations (only .NET 4.0 and above)?
Is performance important, i.e. will my reflected method or instantiation call be called once, twice or a million times?
Can I combine technologies to get to a smart but workable/understandable solution?
Am I ok with losing compile time type safety?
Genericity / dynamic
From your description I assume you do not know the types at compile time, you only know they share the interface ICalculation. If this is correct, then number (1) and (2) above are likely not possible in your scenario.
Performance
This is an important question to ask. The overhead of using reflection can impede a more than 400-fold penalty: that slows down even a moderate amount of calls.
The resolution is relatively easy: instead of using Activator.CreateInstance, use a factory method (you already have that), look up the MethodInfo create a delegate, cache it and use the delegate from then on. This yields only a penalty on the first invocation, subsequent invocations have near-native performance.
Combine technologies
A lot is possible here, but I'd really need to know more of your situation to assist in this direction. Often, I end up combining dynamic with generics, with cached reflection. When using information hiding (as is normal in OOP), you may end up with a fast, stable and still well-extensible solution.
Losing compile time type safety
Of the five questions, this is perhaps the most important one to worry about. It is very important to create your own exceptions that give clear information about reflection mistakes. That means: every call to a method, constructor or property based on an input string or otherwise unchecked information must be wrapped in a try/catch. Catch only specific exceptions (as always, I mean: never catch Exception itself).
Focus on TargetException (method does not exist), TargetInvocationException (method exists, but rose an exc. when invoked), TargetParameterCountException, MethodAccessException (not the right privileges, happens a lot in ASP.NET), InvalidOperationException (happens with generic types). You don't always need to try to catch all of them, it depends on the expected input and expected target objects.
To sum it up
Get rid of your Activator.CreateInstance and use MethodInfo to find the factory-create method, and use Delegate.CreateDelegate to create and cache the delegate. Simply store it in a static Dictionary where the key is equal to the class-string in your example code. Below is a quick but not-so-dirty way of doing this safely and without losing too much type safety.
Sample code
public class TestDynamicFactory
{
// static storage
private static Dictionary<string, Func<ICalculate>> InstanceCreateCache = new Dictionary<string, Func<ICalculate>>();
// how to invoke it
static int Main()
{
// invoke it, this is lightning fast and the first-time cache will be arranged
// also, no need to give the full method anymore, just the classname, as we
// use an interface for the rest. Almost full type safety!
ICalculate instanceOfCalculator = this.CreateCachableICalculate("RandomNumber");
int result = instanceOfCalculator.ExecuteCalculation();
}
// searches for the class, initiates it (calls factory method) and returns the instance
// TODO: add a lot of error handling!
ICalculate CreateCachableICalculate(string className)
{
if(!InstanceCreateCache.ContainsKey(className))
{
// get the type (several ways exist, this is an eays one)
Type type = TypeDelegator.GetType("TestDynamicFactory." + className);
// NOTE: this can be tempting, but do NOT use the following, because you cannot
// create a delegate from a ctor and will loose many performance benefits
//ConstructorInfo constructorInfo = type.GetConstructor(Type.EmptyTypes);
// works with public instance/static methods
MethodInfo mi = type.GetMethod("Create");
// the "magic", turn it into a delegate
var createInstanceDelegate = (Func<ICalculate>) Delegate.CreateDelegate(typeof (Func<ICalculate>), mi);
// store for future reference
InstanceCreateCache.Add(className, createInstanceDelegate);
}
return InstanceCreateCache[className].Invoke();
}
}
// example of your ICalculate interface
public interface ICalculate
{
void Initialize();
int ExecuteCalculation();
}
// example of an ICalculate class
public class RandomNumber : ICalculate
{
private static Random _random;
public static RandomNumber Create()
{
var random = new RandomNumber();
random.Initialize();
return random;
}
public void Initialize()
{
_random = new Random(DateTime.Now.Millisecond);
}
public int ExecuteCalculation()
{
return _random.Next();
}
}
I suggest you give your factory implementation a method RegisterImplementation. So every new class is just a call to that method and you are not changing your factories code.
UPDATE:
What I mean is something like this:
Create an interface that defines a calculation. According to your code, you already did this. For the sake of being complete, I am going to use the following interface in the rest of my answer:
public interface ICalculation
{
void Initialize(string originalData);
void DoWork();
}
Your factory will look something like this:
public class CalculationFactory
{
private readonly Dictionary<string, Func<string, ICalculation>> _calculations =
new Dictionary<string, Func<string, ICalculation>>();
public void RegisterCalculation<T>(string method)
where T : ICalculation, new()
{
_calculations.Add(method, originalData =>
{
var calculation = new T();
calculation.Initialize(originalData);
return calculation;
});
}
public ICalculation CreateInstance(string method, string originalData)
{
return _calculations[method](originalData);
}
}
This simple factory class is lacking error checking for the reason of simplicity.
UPDATE 2:
You would initialize it like this somewhere in your applications initialization routine:
CalculationFactory _factory = new CalculationFactory();
public void RegisterCalculations()
{
_factory.RegisterCalculation<Pivot>("Pivot");
_factory.RegisterCalculation<GroupBy>("GroupBy");
_factory.RegisterCalculation<StandardDeviation>("Standard deviation");
_factory.RegisterCalculation<PhosphoPRASPercentage>("% phospho PRAS Protein");
_factory.RegisterCalculation<AveragePPPperTreatment>("AveragePPPperTreatment");
_factory.RegisterCalculation<AvgPPPNControl>("AvgPPPNControl");
_factory.RegisterCalculation<PercentageInhibition>("PercentageInhibition");
}
Just as an example how to add initialization in the constructor:
Something similar to: Activator.CreateInstance(Type.GetType("ConsoleApplication1.Operation1"), initializationData);
but written with Linq Expression, part of code is taken here:
public class Operation1
{
public Operation1(object data)
{
}
}
public class Operation2
{
public Operation2(object data)
{
}
}
public class ActivatorsStorage
{
public delegate object ObjectActivator(params object[] args);
private readonly Dictionary<string, ObjectActivator> activators = new Dictionary<string,ObjectActivator>();
private ObjectActivator CreateActivator(ConstructorInfo ctor)
{
Type type = ctor.DeclaringType;
ParameterInfo[] paramsInfo = ctor.GetParameters();
ParameterExpression param = Expression.Parameter(typeof(object[]), "args");
Expression[] argsExp = new Expression[paramsInfo.Length];
for (int i = 0; i < paramsInfo.Length; i++)
{
Expression index = Expression.Constant(i);
Type paramType = paramsInfo[i].ParameterType;
Expression paramAccessorExp = Expression.ArrayIndex(param, index);
Expression paramCastExp = Expression.Convert(paramAccessorExp, paramType);
argsExp[i] = paramCastExp;
}
NewExpression newExp = Expression.New(ctor, argsExp);
LambdaExpression lambda = Expression.Lambda(typeof(ObjectActivator), newExp, param);
return (ObjectActivator)lambda.Compile();
}
private ObjectActivator CreateActivator(string className)
{
Type type = Type.GetType(className);
if (type == null)
throw new ArgumentException("Incorrect class name", "className");
// Get contructor with one parameter
ConstructorInfo ctor = type.GetConstructors()
.SingleOrDefault(w => w.GetParameters().Length == 1
&& w.GetParameters()[0].ParameterType == typeof(object));
if (ctor == null)
throw new Exception("There is no any constructor with 1 object parameter.");
return CreateActivator(ctor);
}
public ObjectActivator GetActivator(string className)
{
ObjectActivator activator;
if (activators.TryGetValue(className, out activator))
{
return activator;
}
activator = CreateActivator(className);
activators[className] = activator;
return activator;
}
}
The usage is following:
ActivatorsStorage ast = new ActivatorsStorage();
var a = ast.GetActivator("ConsoleApplication1.Operation1")(initializationData);
var b = ast.GetActivator("ConsoleApplication1.Operation2")(initializationData);
The same can be implemented with DynamicMethods.
Also, the classes are not required to be inherited from the same interface or base class.
Thanks, Vitaliy
One strategy that I use in cases like this is to flag my various implementations with a special attribute to indicate its key, and scan the active assemblies for types with that key:
[AttributeUsage(AttributeTargets.Class)]
public class OperationAttribute : System.Attribute
{
public OperationAttribute(string opKey)
{
_opKey = opKey;
}
private string _opKey;
public string OpKey {get {return _opKey;}}
}
[Operation("Standard deviation")]
public class StandardDeviation : IOperation
{
public void Initialize(object originalData)
{
//...
}
}
public interface IOperation
{
void Initialize(object originalData);
}
public class OperationFactory
{
static OperationFactory()
{
_opTypesByKey =
(from a in AppDomain.CurrentDomain.GetAssemblies()
from t in a.GetTypes()
let att = t.GetCustomAttributes(typeof(OperationAttribute), false).FirstOrDefault()
where att != null
select new { ((OperationAttribute)att).OpKey, t})
.ToDictionary(e => e.OpKey, e => e.t);
}
private static IDictionary<string, Type> _opTypesByKey;
public IOperation GetOperation(string opKey, object originalData)
{
var op = (IOperation)Activator.CreateInstance(_opTypesByKey[opKey]);
op.Initialize(originalData);
return op;
}
}
That way, just by creating a new class with a new key string, you can automatically "plug in" to the factory, without having to modify the factory code at all.
You'll also notice that rather than depending on each implementation to provide a specific constructor, I've created an Initialize method on the interface I expect the classes to implement. As long as they implement the interface, I'll be able to send the "originalData" to them without any reflection weirdness.
I'd also suggest using a dependency injection framework like Ninject instead of using Activator.CreateInstance. That way, your operation implementations can use constructor injection for their various dependencies.
Essentially, it sounds like you want the factory pattern. In this situation, you define a mapping of input to output types and then instantiate the type at runtime like you are doing.
Example:
You have X number of classes, and they all share a common interface of IDoSomething.
public interface IDoSomething
{
void DoSomething();
}
public class Foo : IDoSomething
{
public void DoSomething()
{
// Does Something specific to Foo
}
}
public class Bar : IDoSomething
{
public void DoSomething()
{
// Does something specific to Bar
}
}
public class MyClassFactory
{
private static Dictionary<string, Type> _mapping = new Dictionary<string, Type>();
static MyClassFactory()
{
_mapping.Add("Foo", typeof(Foo));
_mapping.Add("Bar", typeof(Bar));
}
public static void AddMapping(string query, Type concreteType)
{
// Omitting key checking code, etc. Basically, you can register new types at runtime as well.
_mapping.Add(query, concreteType);
}
public IDoSomething GetMySomething(string desiredThing)
{
if(!_mapping.ContainsKey(desiredThing))
throw new ApplicationException("No mapping is defined for: " + desiredThing);
return Activator.CreateInstance(_mapping[desiredThing]) as IDoSomething;
}
}
There's no error checking here. Are you absolutely sure that _class will resolve to a valid class? Are you controlling all the possible values or does this string somehow get populated by an end-user?
Reflection is generally most costly than avoiding it. Performance issues are proportionate to the number of objects you plan to instantiate this way.
Before you run off and use a dependency injection framework read the criticisms of it. =)
I am wondering what it would take to make something like this work:
using System;
class Program
{
static void Main()
{
var f = new IFoo {
Foo = "foo",
Print = () => Console.WriteLine(Foo)
};
}
}
interface IFoo
{
String Foo { get; set; }
void Print();
}
The anonymous type created would look something like this:
internal sealed class <>f__AnonymousType0<<Foo>j__TPar> : IFoo
{
readonly <Foo>j__TPar <Foo>i__Field;
public <>f__AnonymousType0(<Foo>j__TPar Foo)
{
this.<Foo>i__Field = Foo;
}
public <Foo>j__TPar Foo
{
get { return this.<Foo>i__Field; }
}
public void Print()
{
Console.WriteLine(this.Foo);
}
}
Is there any reason that the compiler would be unable to do something like this? Even for non-void methods or methods that take parameters the compiler should be able to infer the types from the interface declaration.
Disclaimer: While I do realize that this is not currently possible and it would make more sense to simply create a concrete class in this instance I am more interested in the theoretical aspects of this.
There would be a few issues with overloaded members, indexers, and explicit interface implementations.
However, you could probably define the syntax in a way that allows you to resolve those problems.
Interestingly, you can get pretty close to what you want with C# 3.0 by writing a library. Basically, you could do this:
Create<IFoo>
(
new
{
Foo = "foo",
Print = (Action)(() => Console.WriteLine(Foo))
}
);
Which is pretty close to what you want. The primary differences are a call to "Create" instead of the "new" keyword and the fact that you need to specify a delegate type.
The declaration of "Create" would look like this:
T Create<T> (object o)
{
//...
}
It would then use Reflection.Emit to generate an interface implementation dynamically at runtime.
This syntax, however, does have problems with explicit interface implementations and overloaded members, that you couldn't resolve without changing the compiler.
An alternative would be to use a collection initializer rather than an anonymous type. That would look like this:
Create
{
new Members<IFoo>
{
{"Print", ((IFoo #this)=>Console.WriteLine(Foo))},
{"Foo", "foo"}
}
}
That would enable you to:
Handle explicit interface implementation by specifying something like "IEnumerable.Current" for the string parameter.
Define Members.Add so that you don't need to specify the delegate type in the initializer.
You would need to do a few things to implement this:
Writer a small parser for C# type names. This only requires ".", "[]", "<>",ID, and the primitive type names, so you could probably do that in a few hours
Implement a cache so that you only generate a single class for each unique interface
Implement the Reflection.Emit code gen. This would probably take about 2 days at the most.
It requires c# 4, but the opensource framework impromptu interface can fake this out of the box using DLR proxies internally. The performance is good although not as good as if the change you proposed existed.
using ImpromptuInterface.Dynamic;
...
var f = ImpromptuGet.Create<IFoo>(new{
Foo = "foo",
Print = ReturnVoid.Arguments(() => Console.WriteLine(Foo))
});
An anonymous type can't be made to do anything except to have read-only properties.
Quoting the C# Programming Guide (Anonymous Types):
"Anonymous types are class types that
consist of one or more public
read-only properties. No other kinds
of class members such as methods or
events are allowed. An anonymous type
cannot be cast to any interface or
type except for object."
As long as we're putting out an interface wish list, I'd really like to be able to tell the compiler that a class implements an interface outside the class definition- even in a separate assembly.
For example, let's say I'm working on a program to extract files from different archive formats. I want to be able to pull in existing implementations from different libraries — say, SharpZipLib and a commercial PGP implementation — and consume both libraries using the same code without creating new classes. Then I could use types from either source in generic constraints, for example.
Another use would be telling the compiler that System.Xml.Serialization.XmlSerializer implements the System.Runtime.Serialization.IFormatter interface (it already does, but the compiler doesn't know it).
This could be used to implement your request as well, just not automatically. You'd still have to explicitly tell the compiler about it. Not sure how the syntax would look, because you'd still have to manually map methods and properties somewhere, which means a lot of verbiage. Maybe something similar to extension methods.
You could have something like anonymous classes in Java:
using System;
class Program {
static void Main() {
var f = new IFoo() {
public String Foo { get { return "foo"; } }
public void Print() { Console.WriteLine(Foo); }
};
}
}
interface IFoo {
String Foo { get; set; }
void Print();
}
Wouldn't this be cool. Inline anonymous class:
List<Student>.Distinct(new IEqualityComparer<Student>()
{
public override bool Equals(Student x, Student y)
{
return x.Id == y.Id;
}
public override int GetHashCode(Student obj)
{
return obj.Id.GetHashCode();
}
})
I'm going to dump this here. I wrote it a while ago but IIRC it works OK.
First a helper function to take a MethodInfo and return a Type of a matching Func or Action. You need a branch for each number of parameters, unfortunately, and I apparently stopped at three.
static Type GenerateFuncOrAction(MethodInfo method)
{
var typeParams = method.GetParameters().Select(p => p.ParameterType).ToArray();
if (method.ReturnType == typeof(void))
{
if (typeParams.Length == 0)
{
return typeof(Action);
}
else if (typeParams.Length == 1)
{
return typeof(Action<>).MakeGenericType(typeParams);
}
else if (typeParams.Length == 2)
{
return typeof(Action<,>).MakeGenericType(typeParams);
}
else if (typeParams.Length == 3)
{
return typeof(Action<,,>).MakeGenericType(typeParams);
}
throw new ArgumentException("Only written up to 3 type parameters");
}
else
{
if (typeParams.Length == 0)
{
return typeof(Func<>).MakeGenericType(typeParams.Concat(new[] { method.ReturnType }).ToArray());
}
else if (typeParams.Length == 1)
{
return typeof(Func<,>).MakeGenericType(typeParams.Concat(new[] { method.ReturnType }).ToArray());
}
else if (typeParams.Length == 2)
{
return typeof(Func<,,>).MakeGenericType(typeParams.Concat(new[] { method.ReturnType }).ToArray());
}
else if (typeParams.Length == 3)
{
return typeof(Func<,,,>).MakeGenericType(typeParams.Concat(new[] { method.ReturnType }).ToArray());
}
throw new ArgumentException("Only written up to 3 type parameters");
}
}
And now the method that takes an interface as a generic parameter and returns a Type that implements the interface and has a constructor (needs to be called via Activator.CreateInstance) taking a Func or Action for each method/ getter/setter. You need to know the right order to put them in the constructor, though. Alternatively (commented-out code) it can generate a DLL which you can then reference and use the type directly.
static Type GenerateInterfaceImplementation<TInterface>()
{
var interfaceType = typeof(TInterface);
var funcTypes = interfaceType.GetMethods().Select(GenerateFuncOrAction).ToArray();
AssemblyName aName =
new AssemblyName("Dynamic" + interfaceType.Name + "WrapperAssembly");
var assBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(
aName,
AssemblyBuilderAccess.Run/*AndSave*/); // to get a DLL
var modBuilder = assBuilder.DefineDynamicModule(aName.Name/*, aName.Name + ".dll"*/); // to get a DLL
TypeBuilder typeBuilder = modBuilder.DefineType(
"Dynamic" + interfaceType.Name + "Wrapper",
TypeAttributes.Public);
// Define a constructor taking the same parameters as this method.
var ctrBuilder = typeBuilder.DefineConstructor(
MethodAttributes.Public | MethodAttributes.HideBySig |
MethodAttributes.SpecialName | MethodAttributes.RTSpecialName,
CallingConventions.Standard,
funcTypes);
// Start building the constructor.
var ctrGenerator = ctrBuilder.GetILGenerator();
ctrGenerator.Emit(OpCodes.Ldarg_0);
ctrGenerator.Emit(
OpCodes.Call,
typeof(object).GetConstructor(Type.EmptyTypes));
// For each interface method, we add a field to hold the supplied
// delegate, code to store it in the constructor, and an
// implementation that calls the delegate.
byte methodIndex = 0;
foreach (var interfaceMethod in interfaceType.GetMethods())
{
ctrBuilder.DefineParameter(
methodIndex + 1,
ParameterAttributes.None,
"del_" + interfaceMethod.Name);
var delegateField = typeBuilder.DefineField(
"del_" + interfaceMethod.Name,
funcTypes[methodIndex],
FieldAttributes.Private);
ctrGenerator.Emit(OpCodes.Ldarg_0);
ctrGenerator.Emit(OpCodes.Ldarg_S, methodIndex + 1);
ctrGenerator.Emit(OpCodes.Stfld, delegateField);
var metBuilder = typeBuilder.DefineMethod(
interfaceMethod.Name,
MethodAttributes.Public | MethodAttributes.Virtual |
MethodAttributes.Final | MethodAttributes.HideBySig |
MethodAttributes.NewSlot,
interfaceMethod.ReturnType,
interfaceMethod.GetParameters()
.Select(p => p.ParameterType).ToArray());
var metGenerator = metBuilder.GetILGenerator();
metGenerator.Emit(OpCodes.Ldarg_0);
metGenerator.Emit(OpCodes.Ldfld, delegateField);
// Generate code to load each parameter.
byte paramIndex = 1;
foreach (var param in interfaceMethod.GetParameters())
{
metGenerator.Emit(OpCodes.Ldarg_S, paramIndex);
paramIndex++;
}
metGenerator.EmitCall(
OpCodes.Callvirt,
funcTypes[methodIndex].GetMethod("Invoke"),
null);
metGenerator.Emit(OpCodes.Ret);
methodIndex++;
}
ctrGenerator.Emit(OpCodes.Ret);
// Add interface implementation and finish creating.
typeBuilder.AddInterfaceImplementation(interfaceType);
var wrapperType = typeBuilder.CreateType();
//assBuilder.Save(aName.Name + ".dll"); // to get a DLL
return wrapperType;
}
You can use this as e.g.
public interface ITest
{
void M1();
string M2(int m2, string n2);
string prop { get; set; }
event test BoopBooped;
}
Type it = GenerateInterfaceImplementation<ITest>();
ITest instance = (ITest)Activator.CreateInstance(it,
new Action(() => {Console.WriteLine("M1 called"); return;}),
new Func<int, string, string>((i, s) => "M2 gives " + s + i.ToString()),
new Func<String>(() => "prop value"),
new Action<string>(s => {Console.WriteLine("prop set to " + s);}),
new Action<test>(eh => {Console.WriteLine(eh("handler added"));}),
new Action<test>(eh => {Console.WriteLine(eh("handler removed"));}));
// or with the generated DLL
ITest instance = new DynamicITestWrapper(
// parameters as before but you can see the signature
);
Interesting idea, I'd be a little concerned that even if it could be done it might get confusing. E.g. when defining a property with non-trivial setters and getters, or how to disambiguate Foo if the the declaring type also contained a property called Foo.
I wonder if this would be easier in a more dynamic language, or even with the dynamic type and DLR in C# 4.0?
Perhaps today in C# some of the intent could be achieved with lambdas:
void Main() {
var foo = new Foo();
foo.Bar = "bar";
foo.Print = () => Console.WriteLine(foo.Bar);
foo.Print();
}
class Foo : IFoo {
public String Bar { get; set; }
public Action Print {get;set;}
}
This wouldn't be possible currently.
What would be the difference between this and simply making IFoo a concrete class instead? Seems like that might be the better option.
What it would take? A new compiler and tons of checks to ensure they didn't break the other features. Personally, I think it'd just be easier to require developers to just create a concrete version of their class.
I have used in Java the Amonimous Class through the "new IFoo(){...}" sintax and it's practical and easy when you have to quick implement a simple interface.
As a sample it would be nice to implement IDisposable this way on a legacy object used just one time instead of deriving a new class to implement it.
I have an abstract generic class BLL<T> where T : BusinessObject. I need to open an assembly that contains a set of concrete BLL classes, and return the tuples (businessObjectType, concreteBLLType) inside a Dictionary. There is the part of the method I could do until now, but I'm having problems to discover T.
protected override Dictionary<Type, Type> DefineBLLs()
{
string bllsAssembly = ConfigurationManager.AppSettings["BLLsAssembly"];
Type[] types = LoadAssembly(bllsAssembly);
Dictionary<Type, Type> bllsTypes = new Dictionary<Type, Type>();
foreach (Type type in types)
{
if (type.IsSubclassOf(typeof(BLL<>)))
/* how to know T in the situation below? */
bllsTypes.Add(??businessObjectType (T)??, type);
}
return bllsTypes;
}
So the concrete classes will be closed rather than generic? Here's a short program which demonstrates what I think you're after...
using System;
using System.Reflection;
public abstract class Base<T>
{
}
public class Concrete : Base<string>
{
}
class Test
{
static void Main()
{
Type type = typeof(Concrete);
Type baseType = type.BaseType;
Type typeOfT = baseType.GetGenericArguments()[0]; // Only one arg
Console.WriteLine(typeOfT.Name); // Prints String
}
}
Note that here I'm assuming that we only need to go up one level to get to the appropriate base type, and that the concrete class will be closed. You'd want to put more checks into your real code, of course, but I suspect it was the call to GetGenericArguments that you were missing.
Jon, that is exactly what I was looking for. I use the basics of reflection and generics, so when it is needed a more profound knowledge of the API to confront both, I miss things like this one, thanks for answering.
Your assumptions are right, the concrete classes are closed, and T is defined on the base class (BLL).
The code became into this:
protected override Dictionary<Type, Type> DefineBLLs()
{
string bllsAssembly = ConfigurationManager.AppSettings["BLLsAssembly"];
Type[] types = LoadAssembly(bllsAssembly);
Dictionary<Type, Type> bllsTypes = new Dictionary<Type, Type>();
foreach (Type bllType in types)
{
if (bllType.IsSubclassOf(typeof(BLL<>)))
{
Type baseType = bllType.BaseType;
Type businessObjectType = baseType.GetGenericArguments()[0];
bllsTypes.Add(businessObjectType, bllType);
}
}
return bllsTypes;
}