I know a refactor safe way to get the name of a property with this answer. Is there a refactor safe way to get the name of a method?
I am using C# 5 and .Net 4.5.
To illustrate what I'm trying to do:
class MyClass
{
public void UnitTestOne() { /* impl */ }
public void UnitTestTwo() { /* impl */ }
public void UnitTestThree()
{
//I'd like to get the method names for UnitTestOne and UnitTestTwo here
//in such a way that this code will raise a compile time error if either
//the UnitTestOne or UnitTestTwo method names changes.
}
}
UPDATE: Here is a nice post that explains and provides a flexible utility method to access MethodInfos with refactor safe code. http://www.codeducky.org/10-utilities-c-developers-should-know-part-two/
I think Jon Skeet's answer is fine if you only want to cover void parameterless methods. A more general solution would look like this:
public class MyClass
{
public void UnitTestOne(int i) { /* impl */ }
public int UnitTestTwo() { /* impl */ }
public void UnitTestThree()
{
var methodCallExpressions = new Expression<Action<MyClass>>[] {
mc => mc.UnitTestOne(default(int)), //Note that a dummy argument is provided
mc => mc.UnitTestTwo()
};
var names = methodCallExpressions.Select(mce =>
((MethodCallExpression) mce.Body).Method.Name);
}
}
Note that we use an array of Expression<Action<MyClass>> in order to make a list of method calls on MyClass without knowing the return type and parameter types of each method call. Each method call expression is provided dummy variables to instantiate the expression.
Then the body of each expression is cast to a MethodCallExpression which, as the type name indicates, holds an expression which is just the calling of a method. That type has a Method property which is the MethodInfo of the method being called.
In the link you provided, a property name is extracted similarly using a MemberExpression. Using MethodCallExpression makes the examples quite similar.
By the way, you can also use Expression<Action> instead of Expression<Action<MyClass>> if you prefer. Replace the methodCallExpressions instantiation with:
var methodCallExpressions = new Expression<Action>[] {
() => this.UnitTestOne(default(int)),
() => this.UnitTestTwo()
};
I see this as mostly a stylistic decision, although it would also allow you to encapsulate method calls on a different class, using something like () => (new MyClass2()).UnitTestThree().
The simplest way is probably just to create a delegate for each method, and use the MulticastDelegate.Method property:
class MyClass
{
public void UnitTestOne() { /* impl */ }
public void UnitTestTwo() { /* impl */ }
public void UnitTestThree()
{
var actions = new Action[] { UnitTestOne, UnitTestTwo };
var names = actions.Select(x => x.Method.Name);
}
}
Related
I want to store a method call in an action. That method is a static method, but with a string argument that varies. So I want to store "call StaticMethod with argument "myString" in an Action.
But... without capturing this.
I can store an anonymous method () => StaticMethod(myString) in the action , but this captures the action target (this). (Edit: it doesn't. See the accepted answer).
I can store the static method in the action, but then I'm missing the argument.
I could store the static method and the arguments separately, but due to technical reasons, this is cumbersome and ugly.
Do I have any other possibility?
[Edit]
In other words, I want to do this:
private void MyMethod(string myString){
var action = Call StaticMethod with argument myString.
}
And somewhere else, where I have access to action, but don't know anything about the string, or that there are arguments:
action.Invoke();
action can capture the string, but can't capture this (the call target of MyMethod).
Given the following assumptions:
myString is a local variable, or a parameter to the method (Not! a property or field)
StaticMethod is really a static method
There are no other delegates being constructed in the same method as you want to construct action
then the following:
public void M() {
string myString = "something";
Action action = () => StaticMethod(myString);
}
public static void StaticMethod(string value) { }
will be compiled as this:
[CompilerGenerated]
private sealed class <>c__DisplayClass0_0
{
public string myString;
internal void <M>b__0()
{
StaticMethod(myString);
}
}
public void M()
{
<>c__DisplayClass0_0 <>c__DisplayClass0_ = new <>c__DisplayClass0_0();
<>c__DisplayClass0_.myString = "something";
Action action = new Action(<>c__DisplayClass0_.<M>b__0);
}
As you can see, your lambda is lifted out to a generated display class, and myString is also lifted out from your method, going from a local variable to a field on that display class. This is the closure, and the object constructed in the M method will be the target of the action, and this closure will not capture this.
You can see this in action here: SharpLab
Note that small changes to your code will invalidate this as the assumptions change. For instance, if you also, in the same method, declare another delegate that also requires a closure and also requires access to this, then the same closure will be shared between the two delegates.
Example:
public void M() {
string myString = "something";
Action action = () => StaticMethod(myString);
Action otherAction = () => StaticMethod(Property);
}
public string Property => "Value";
Generates this code:
[CompilerGenerated]
private sealed class <>c__DisplayClass0_0
{
public string myString;
public C <>4__this;
internal void <M>b__0()
{
StaticMethod(myString);
}
internal void <M>b__1()
{
StaticMethod(<>4__this.Property);
}
}
public string Property
{
get
{
return "Value";
}
}
public void M()
{
<>c__DisplayClass0_0 <>c__DisplayClass0_ = new <>c__DisplayClass0_0();
<>c__DisplayClass0_.<>4__this = this;
<>c__DisplayClass0_.myString = "something";
Action action = new Action(<>c__DisplayClass0_.<M>b__0);
Action action2 = new Action(<>c__DisplayClass0_.<M>b__1);
}
As you can see, the same closure is used to support both delegates, and now both delegates has a reference to a closure that captures this.
If you can't define your action at call site at compile time e.:
Action a = () => StaticMethod("myString");
Then you will probably want to use expressions for this.
Example Code:
[Fact]
public void SampleActionWithoutThisScopeTests()
{
// Using Compile Time Action
Action compileTimeAction = () => MyStaticMethod("CompileTime myString");
compileTimeAction.Invoke();
// Using Compiled Expression
var myString = "Expression myString";
var methodInfo = this.GetType().GetMethod(nameof(MyStaticMethod), BindingFlags.Static | BindingFlags.Public);
var stringArgumentConstant = Expression.Constant(myString);
var callExpression = Expression.Call(null, methodInfo, stringArgumentConstant);
var lambda = Expression.Lambda<Action>(callExpression);
var action = lambda.Compile();
action.Invoke();
}
public static void MyStaticMethod(string input)
{
Console.WriteLine(input);
}
EDIT
If you can, and meet the requirements for the compiler-generated closure to not contain "this" via normal lambda syntax (see #Lasse V. Karlsen answer, then definitely use that approach!
We are creating a configuration API for some of our internal projects. The API is replacing an attribute-based configuration. The new API involves specifying methods within a class along with the options that go with it.
public static class Configuration<T> {
public static void ForMethod(Expression<Action<T>> methodExpression, Options options) { //Option-1
MethodInfo method = GetMethod(methodExpression);
// do something with options
}
public static void ForMethod<TResult>(Expression<Func<T,TResult>> methodExpression, Options options) { //Option-2
MethodInfo method = GetMethod(methodExpression);
// do something with options
}
private static MethodInfo GetMethod(Expression expression) {
// there's other checks done, but this is what it boils down to
var methodCall = (MethodCallExpression) expression.Body;
return methodCall.Method;
}
}
class MyClass {
void MyMethod() { ... }
}
Configuration<MyClass>.ForMethod(x => x.MyMethod(), ... );
This is great except for when the methods themselves have parameters. IE
class MyClass2 {
void MyMethod2(int x) { }
int SomeOtherMethod(int x) { return x*x; }
}
These can be handled by expanding the configuration class like:
public static void ForMethod<TResult, TIn>(Expression<Func<T,TIn,TResult>> methodExpression, ...) { //Option-3
}
// and then called:
Configuation<MyClass2>.ForMethod<int,int>((x,y) => x.SomeOtherMethod(y), ...);
As more parameters get added it becomes a bit more clumsy. Technically we don't care about the parameters themselves, so long as we select the correct method. We could get around this by simply specifying everything as Option-1 (since we can also ignore the return type and specify everything as Actions) and just specifying the parameters using the default keyword, ie:
Configuration<MyClass2>.ForMethod(x => x.SomeOtherMethod(default(int)), ...)
However, this gets quite ugly.
Is there any way with type inference (or some other magic) to select the appropriate method without needing to explicitly state the parameter types? My hope would be something like this (although this do not work)
Configuration<MyClass2>.ForMethod((x,y) => x.SomeOtherMethod(y), ...) // Option 3 with return type and type of input inferred
or even
Configuration<MyClass2>.ForMethod((x,y) => x.SomeOtherMethod, ...) // Option 3 with return type and input 1 inferred + as method group
My gut tells me that this is not possible as I haven't been able to find any way around this online. My hope is that perhaps with a combination of extension methods and type inference this could be made possible, but I'm having difficulty finding anything that compiles. Is this even possible?
I have the following type hierarchy:
public abstract class Controller {}
public sealed class PersonController : Controller {}
public sealed class OrderController : Controller {}
I also have a method that resolves the instance of a given type on demand (think of it as a layman's IOC):
private void Resolve<T>(Func<T>[] controllerFactories) where T : Controller
{
Array.ForEach(controllerFactories, x =>
{
// This returns Controller instead of the child class
// I need to know the actual type so that I can do other stuff
// before resolving the instance.
Console.WriteLine(x.Method.ReturnType);
var controllerInstance = x();
});
}
I need to figure out the type of T in Func<T> but when I try:
void Main()
{
var factories = new Func<Controller>[] {
() => new PersonController(),
() => new OrderController()
};
Resolve(factories);
}
I get Controller instead of the PersonController and OrderController.
Any ideas?
Update:
I thank everyone for providing such detailed answers and examples. They prompted me to rethink the API and here is what I finally came up with which serves what I wanted to accomplish:
public interface IResolver<T>
{
void Register<TKey>(Func<TKey> factory) where TKey : T;
T Resolve(Type type);
void ResolveAll();
}
public sealed class ControllerResolver : IResolver<Controller>
{
private Dictionary<Type, Func<Controller>> _factories = new Dictionary<Type, Func<Controller>>();
public void Register<TKey>(Func<TKey> factory) where TKey : Controller
{
_factories.Add(typeof(TKey), factory);
}
public Controller Resolve(Type type) => _factories[type]();
public void ResolveAll()
{
foreach (var pair in _factories)
{
// Correctly outputs what I want
Console.WriteLine(pair.Value.Method.ReturnType);
}
}
}
And here are some usage examples:
void Main()
{
var resolver = new ControllerResolver();
resolver.Register(() => new PersonController());
resolver.Register(() => new OrderController());
resolver.ResolveAll();
resolver.Resolve(typeof(PersonController));
}
Each method has a return type stored in the assembly, you specified that your methods' return type is Controller. This is the only thing that is guaranteed as an information (That is what we know without executing the method - Also at compile time)
So we know that the method should return Controller or anything that derive from that. We can never know what is the run-time type until we actually call that method.
As an example, what if the method has a code like:
var factories = new Func<Controller>[] {
() =>
{
if ( DateTime.Now.Second % 2 == 0 )
return new OrderController();
else
return new PersonController();
}
};
If you need to get the run-time type of the object returned, then you need to:
var controllerInstance = x();
Console.WriteLine(controllerInstance.GetType().Name);
Lambdas in C# get their type based on the expression they are assigned to. For example, this:
Func<string, string> d = x => x;
Makes the lambda x => x a string => string function, on the grounds that this is what the variable d expects.
Why is this relevant? Because in the following code, you're creating a similar expectation for the following lambdas:
var factories = new Func<Controller>[] {
() => new PersonController(),
() => new OrderController()
};
The expectation is that these lambdas are of the Func<Controller> type. If the compiler was looking at the lambda bodies for the type, it would arrive at a different conclusion, specifically that one is a Func<PersonController> and the other is a Func<OrderController>, both of which are kinds of Func<Controller>. But the compiler doesn't look at the body for the type, it looks at the variable and the "variable" in this case is the array slot.
Thus, the compiler will generate these delegates not as these methods:
PersonController Delegate1()
{
return new PersonController();
}
OrderController Delegate2()
{
return new OrderController();
}
But as these methods:
Controller Delegate1()
{
return new PersonController();
}
Controller Delegate2()
{
return new OrderController();
}
Therefore, by the time these delegates are inserted into the array, only the type information of the signatures remain, while the actual type information of the lambda bodies is lost.
But there is one way to maintain the information about the lambda bodies, and then inspect that information instead of the delegate signatures. You can use of expression trees, which are a way to tell the compiler to treat code as data and essentially generate tree objects that represent the lambda, instead of the actual method that implements the lambda.
Their syntax is nearly identical to that of lambdas:
var factories = new Expression<Func<Controller>>[] {
() => new PersonController(),
() => new OrderController()
};
The difference is that now these objects aren't functions, but rather representations of functions. You can traverse those representation and very easily find the type of their top-level expression:
var t0 = factories[0].Body.Type; // this is equal to typeof(PersonController)
var t1 = factories[1].Body.Type; // this is equal to typeof(OrderController)
Finally, you can also turn these representations into actual functions, if you also intend to run them:
Func<Controller>[] implementations = factories.Select(x => x.Compile()).ToArray();
The problem is that the same T has to apply to every type in your array. In
private void Resolve<T>(Func<T>[] controllerFactories) where T : Controller
{
Array.ForEach(controllerFactories, x =>
{
// This returns Controller instead of the child class
Console.WriteLine(x.Method.ReturnType);
var controllerInstance = x();
});
}
what is your T? Is it PersonController? Is it OrderController? To make it fit your use case, it can only be a class that is a superclass of both PersonController and OrderController, while being a subclass of Controller. Therefore T can only be one class: Controller (assuming the two classes don't have a common base class that extends Controller). There is no point in making this class generic. It is exactly the same as this:
private void Resolve(Func<Controller>[] controllerFactories)
{
Array.ForEach(controllerFactories, x =>
{
Console.WriteLine(x.Method.ReturnType);
var controllerInstance = x();
});
}
Instead of an array of Func<Controller> instances, it may make more sense to pass in a dictionary keyed on your return type:
var factories = new Dictionary<Type, Func<Controller>> {
[typeof(PersonController)] = () => new PersonController(),
[typeof(OrderController)] = () => new OrderController()
};
An instance of Func<Controller> simply does not contain enough information to determine the type of its return value on its own: not without evaluating it. And even if you evaluate it, remember that a function is a black box. Just because it returns a PersonController once doesn't mean that it won't return an OrderController the next time you invoke it.
This is how it works, when you are instantiating your array, you are specifying that it would be storing Func objects of type Controller, now you are instantiating the sub types objects inside the array of Func, the Resolve, does not know what is the actual type unless you call GetType() to determine the actual type of it, it just knows that the T will be of type Controller because of the constraint i.e where T : Controller
If I have a class like this:
public class SomeClass
{
public Action<string> SomeAction { get; set; }
public SomeClass()
{
SomeAction = GetSomeAnonymousMethod();
}
private Action<string> GetSomeAnonymousMethod()
{
return (text) =>
{
Console.WriteLine(text);
};
}
}
What happens when I make a new instance of SomeClass? My impression is that the constructor simply calls GetSomeAnonymousMethod(), which returns a new delegate instance (that only contains a reference to the compiler-generated backing method for the anonymous method), and assigns it to the SomeAction property.
Can someone confirm, or is something more sinister happening?
Well, that's nearly all that happens. In this particular case, your lambda expression (it's not an anonymous method, to be picky) doesn't need any state, so the generated method can be static, and a delegate reference can be cached. So the "new delegate instance" part may not be correct.
So it's more like this - at least when compiled with the MS compiler:
public class SomeClass
{
private static Action<string> cachedAction;
public Action<string> SomeAction { get; set; }
public SomeClass()
{
SomeAction = GetSomeAnonymousMethod();
}
private Action<string> GetSomeAnonymousMethod()
{
Action<string> action = cachedAction;
if (action == null)
{
action = AnonymousMethodImplementation;
cachedAction = action;
}
return action;
}
private static void AnonymousMethodImplementation(string text)
{
Console.WriteLine(text);
}
}
You don't need to worry about the details of this - and it's all an implementation detail... just a bit of an optimization. But if you really want to know what's going on, that's closer to reality.
As ever, to see the details of what the compiler's doing, you can always use ildasm (or Reflector in IL mode, for example) and see the generated IL.
Can someone confirm, or is something more sinister happening?
It seems like it's another secret action within the events of new and 2nd Cold War!
Yes, your constructor is doing what you're describing in your question.
I would explain that the anonymous delegate is converted into Action<string> using delegate type inference.
For example, the following code line:
return (text) =>
{
Console.WriteLine(text);
};
...is infered to:
return new Action<string>((text) =>
{
Console.WriteLine(text);
});
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. =)