I have a disposable class like this :
public class Person:IDisposable
{
public string Name{get;set;}
public void Dispose()
{}
}
and here's a set of extensions methods that returns a default value if the caller is null:
static class Extensions
{
public class Option<T>
{
private readonly Func<T> _resultGetter;
public bool HasValue { get; }
public Option(Func<T> resultGetter, bool hasValue)
{
_resultGetter = resultGetter;
HasValue = hasValue;
}
public T Value => _resultGetter();
}
public static Option<TResult> SafeGetter<T, TResult>(this T self, Func<T, TResult> getter, Func<TResult> defaultGetter = null) where T : class
{
defaultGetter = defaultGetter ?? (() => default(TResult));
return new Option<TResult>(self == null ? defaultGetter :()=> getter(self),self!=null);
}
}
As you can see the SafeGetter method returns an Option object that has a getter function that has a self parameter as closure.
So to test the getter function after an object is disposed I wrote a test like this :
public void SafeGetterDisposableTest()
{
Extensions.Option<string> nameGetter;
using (var john = new Person { Name = "John" })
{
nameGetter = john.SafeGetter(x => x.Name);
}
Console.WriteLine(nameGetter.Value);
}
as you can see I have got the Option object and call it after john is disposed. I thought that I would get an exception but to my surprise the test is working.
Why this is happening ? Does this code somehow introduce memory leak ?
I thought that I would get an exception but to my surprise the test is
working.
You do not receive an ObjectDisposedException (or any other exception for that matter) just by simply implementing IDisposable. Your Dispose method is empty, and doesn't alter the object even after it has been called by your using statement. If you alter it to throw an exception in your getter after the object has been disposed, you'll get an exception. Otherwise, nothing will happen.
It is a convention that IDisposable objects be implemented such that they'll throw an exception when their members are accesses after they've been disposed. This is not behavior of the language. If your disposable object actually had an umanaged resource that it was using, and then cleaned up, then presumably an operation you perform after its been disposed wouldn't work properly, even if you didn't explicitly throw, hence the convention.
Related
I am trying to serialize objects of class Reference at the end of my program. A serialization exception is thrown, which complains that "DataAnalysis.Reference+<>c__DisplayClass4" is not marked as serializable.
Initially I had the two delegates without the Serializable attribute, so I gave it a try, but it didn't change anything. The classes Cacheable and Operation are already marked as Serializable - and in fact the serialization of the both of them worked perfectly fine before I introduced the Reference class.
I don't even know what c__DisplayClass4 means. So I am sorry, but I don't know what other parts of my 1 megabytes+ source code to post here to help you solve the problem, because in the end I would be posting everything.
As I said, everything worked fine before introducing the Reference class. So I am hoping the problem is somehow localized to it.
using System;
using System.Reflection;
namespace DataAnalysis
{
/// <summary>
/// Description of Reference.
/// </summary>
[Serializable]
public class Reference
{
[Serializable]
public delegate void ReferenceSetter(Operation op, Cacheable c);
[Serializable]
public delegate Cacheable ReferenceGetter(Operation op);
readonly ReferenceGetter refGetter;
readonly ReferenceSetter refSetter;
public Reference(ReferenceGetter getter, ReferenceSetter setter)
{
refGetter = getter;
refSetter = setter;
}
public Reference(FieldInfo operationField)
{
refGetter = (op => (Cacheable)operationField.GetValue(op));
refSetter = ((op, value) => operationField.SetValue(op, value));
}
public Cacheable this[Operation op]
{
get {return refGetter(op);}
set {refSetter(op, value);}
}
}
}
Edit: I have chosen taffer's first solution (avoid using the FieldInfo inside a delegate):
public class Reference
{
public delegate void ReferenceSetter(Operation op, Cacheable c);
public delegate Cacheable ReferenceGetter(Operation op);
readonly FieldInfo opField;
readonly ReferenceGetter refGetter;
readonly ReferenceSetter refSetter;
public Reference(ReferenceGetter getter, ReferenceSetter setter)
{
refGetter = getter;
refSetter = setter;
}
public Reference(FieldInfo operationField)
{
opField = operationField;
}
public Cacheable this[Operation op]
{
get
{
if (opField != null) return (Cacheable)opField.GetValue(op);
else return refGetter(op);
}
set
{
if (opField != null) opField.SetValue(op, value);
else refSetter(op, value);
}
}
}
Not polished yet, I will probably finally use an abstract Reference class with two implementations. But the principle becomes clear.
You get the error because of the way you initialize your fields in the second constructor:
public Reference(FieldInfo operationField)
{
// operationField is captured in the lambda below, which causes to generate an inner class
// where operationField will be a field so can be accessed by the method of the lambda body
refGetter = (op => (Cacheable)operationField.GetValue(op));
refSetter = ((op, value) => operationField.SetValue(op, value));
}
Solution 1:
Do not capture locals and parameters of the enclosing method in the lambda. The field should rather be a parameter of the delegate.
Solution2:
Implement ISerializable and provide a custom serialization:
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("getter", refGetter);
info.AddValue("setter", refSetter);
}
// the special constructor needed for deserialization
private Reference(SerializationInfo info, StreamingContext context)
{
refGetter = (ReferenceGetter)info.GetValue("getter", typeof(ReferenceGetter));
refSetter = (ReferenceSetter)info.GetValue("setter", typeof(ReferenceSetter));
}
Please note that deserializing delegates of non-static methods can be problematic. Maybe you should check the Delegate.Method property in GetObjectData and throw an exception if the setter or getter is an instance method.
A sample code I tried to return an instance of class is given below.
public object getConstructorclass(int i)
{
if(i==1)
{
Type type = Type.GetType("test1");
}else
{
Type type = Type.GetType("test2");
}
return Activator.CreateInstance(type);
}
var objcls = getConstructorclass(1);
objcls.callclass();//error occured
How can I mention the class type here since the type is not known at compile time but it will decided at runtime.In the above example i just pass a value 1 (it can be anything and that class will be called accordingly), and the class test1 called.
here I will get an error on the line objcls.callclass(), because objcls is an object instance that doesn't have a callclass()method.
How can I restructure this piece of code? My aim is if I mention a class in the getConstructorclass() method, an object should be returned so as to use it in the further code to invoke the members of that class.
If you know that your classes will have this method, you should use a common interface for them and implement it accordingly. Then you will work with classes that you have made sure it will work.
It would look like this
IMyInterface objcls = getconstrorclass() as IMyInterface;
if (objcls != null)
objcls.callclass();
else
// we failed miserably and should do something about it
I don't think you should use some generic object returning constructor based on an int variable, if your classes don't have anything in common. It's really weird to handle it like this and it may lead to various problems (some of which you're currently already experiencing). Generic class constructors make sense if the classes are somewhat related and you can predict the outcome, but to create a do-it-all method.. Not so sure about correctness of such approach.
Anyway, if you insist (not recommended, but as you wish), you can create some checks for a type like this:
var createdObject = getConstructorclass(1);
if (createdObject is MyClass1)
{
var specificObject = (MyClass1)createdObject;
specificObject.callMethod1();
}
else if (createdObject is MyClass2)
{
var specificObject = (MyClass2)createdObject;
specificObject.callSomeOtherMethod();
}
...
But it gets very error prone soon, refactoring will probably be a nightmare etc., but it's your call..
Or you maybe can use solution from pwas, but to me it seems unnecessarily complicated for such a basic task. Looks nice and all, but it still returns only the type "object", so it doesn't really solve your specific problem.
Also, to address one issue I'm not sure you understand - you've already created the instance, you just return type object. That is why you can't call any specific methods on this object, because first you have to cast it to something, that actually has that method and make sure the cast can be done (inheritance etc).
If interface solution (see other answers) is enough, don't look at this answer. When you can't use common base class / interface and you still want call members, you can use solution with is keyword (and check types). Instead of writing many ifs for each case, you can use fluent API:
object obj = this.getConstructorclass();
obj.StronglyInvoke()
.When<int>(value => Console.WriteLine("Got {0} as int", value))
.When<string>(value => Console.WriteLine("Got {0} as string", value))
.OnFail(() => Debug.Write("No handle."))
.Invoke();
Solution:
public class GenericCaller
{
private IList<GenericInvoker> invokers = new List<GenericInvoker>();
private readonly object target;
private Action failAction;
public GenericCaller(object target)
{
if (target == null)
{
throw new ArgumentNullException("target");
}
this.target = target;
}
public GenericCaller OnFail(Action fail)
{
this.failAction = fail;
return this;
}
public GenericCaller When<T>(Action<T> then)
{
if (then == null)
{
throw new ArgumentNullException("then");
}
var invoker = new GenericInvoker<T>(this.target, then);
this.invokers.Add(invoker);
return this;
}
public void Invoke()
{
if (this.invokers.Any(invoker => invoker.Invoke()))
{
return;
}
if (this.failAction == null)
{
throw new InvalidOperationException("Handler not found");
}
this.failAction();
}
public abstract class GenericInvoker
{
protected readonly object target;
protected GenericInvoker(object target)
{
this.target = target;
}
public abstract bool Invoke();
}
public class GenericInvoker<T> : GenericInvoker
{
private readonly Action<T> then;
public GenericInvoker(object target, Action<T> then)
: base(target)
{
this.then = then;
}
public override bool Invoke()
{
if (this.target.GetType() == typeof(T))
{
this.then((T)this.target);
return true;
}
return false;
}
}
}
public static class Extensions
{
public static GenericCaller StronglyInvoke(this object o)
{
return new GenericCaller(o);
}
}
Remeber - it would be more elegant to use common interface (as other answers say) - my is only alternative way.
Declare your variable as dynamic
dynamic objcls = getconstrorclass();
Using this the will be determined at run-time, whatever the getconstrorclass method returns. You can access any member of the type and you won't get any error at compile-time. But if you try to access a member which doesn't exists you will get a RuntimeBinderException at runtime.
I would recommend using an interface and restricting the classes that you can instantiate this way to only those that implement the interface.
public interface IMyInterface
{
void callclass();
}
public <T> getConstructorClass()
{
T instance;
Type type = Type.GetType("test1");
// instance will be null if the object cannot be cast to type T.
instance = Activator.CreateInstance(type) as T;
return T;
}
IMyInterface objcls = getConstructorClass<IMyInterface>();
if(null != objcls)
{
objcls.callclass();
}
not sure what you want to achieve in the end, but this looks like a job for "Dependency Injection" - here is a nice sample using autofac
In this article Avoid Null Checks by replacing finders with tellers
the author gives a Ruby example to avoid null checking, if the object is returned the block is run, if not then it isn't.
data_source.person(id) do |person|
person.phone_number = phone_number
data_source.update_person person
end
I'd like to do the same thing in C# using a lambda function but am having trouble coming up with an example that does the same type of thing. Would you create the object factory to accept the id number and also a lambda function?
Well I don't know Ruby and don't understand the exact example given, but I suspect it would be something like:
dataSource.Update(id, person => person.PhoneNumber = phoneNumber);
Where DataSource.Update would:
Have a signature of something like void Update(string id, Action<Person> updateAction (or possibly return a bool to indicate whether or not it found the person)
Be implemented as:
Find the person with the given ID
If it doesn't exist, return immediately
Otherwise, execute the given action, and update the backing store with the modified object
Or more generally (and closer to the original Ruby):
dataSource.WithPerson(id, person => {
person.PhoneNumber = phoneNumber;
dataSource.UpdatePerson(person);
};
Personally I prefer the first form: it's more specific about what it's trying to achieve, but that may well lend itself to a better implementation, and it's certainly cleaner in the calling code.
An alternative approach would be to use the Maybe monad.
This would allow you to keep your existing API as is, i.e. you can still have a dataSource.GetPersonById(id).
Code that uses the Maybe monad looks like this:
dataSource.GetPersonById(id)
.Maybe()
.Do(person => {
person.PhoneNumber = phoneNumber;
dataSource.UpdatePerson(person);
});
To be able to use the Maybe monad you would need to have the code in the following paragraph.
The base for it has been the code from the linked blog post by Daniel Earwicker.
I extended it to add the Maybe extension method and made it compile.
public struct MaybeMonad<T> where T : class
{
private readonly T _value;
public MaybeMonad(T value)
{
_value = value;
}
public MaybeMonad<TResult> Select<TResult>(Func<T, TResult> getter)
where TResult : class
{
var result = (_value == null) ? null : getter(_value);
return new MaybeMonad<TResult>(result);
}
public TResult Select<TResult>(Func<T, TResult> getter,
TResult alternative)
{
return (_value == null) ? alternative : getter(_value);
}
public void Do(Action<T> action)
{
if (_value != null)
action(_value);
}
}
public static class Maybe
{
public static MaybeMonad<T> From<T>(T value) where T : class
{
return new MaybeMonad<T>(value);
}
}
public static class MaybeMonadExtensions
{
public static MaybeMonad<T> Maybe<T>(this T value) where T : class
{
return new MaybeMonad<T>(value);
}
}
In C#, I have a function that passes in T using generics and I want to run a check to see if T is an object that implements a interface and if so call one of the methods on that interface.
I don't want to have T constraints to only be of that Type. Is it possible to do this?
For example:
public class MyModel<T> : IModel<T> where T : MyObjectBase
{
public IQueryable<T> GetRecords()
{
var entities = Repository.Query<T>();
if (typeof(IFilterable).IsAssignableFrom(typeof(T)))
{
//Filterme is a method that takes in IEnumerable<IFilterable>
entities = FilterMe(entities));
}
return entities;
}
public IEnumerable<TResult> FilterMe<TResult>(IEnumerable<TResult> linked) where TResult : IFilterable
{
var dict = GetDict();
return linked.Where(r => dict.ContainsKey(r.Id));
}
}
The error that I am getting is:
Error 21 The type 'TResult' cannot be used as type parameter 'TResult' in the generic type or method 'FilterMe(System.Collections.Generic.IEnumerable)'. There is no implicit reference conversion from 'TResult' to 'IFilterable'.
The missing piece is Cast<>():
if(typeof(IFilterable).IsAssignableFrom(typeof(T))) {
entities = FilterMe(entities.Cast<IFilterable>()).AsQueryable().Cast<T>();
}
Note the use of Cast<>() to convert the entities list to the correct subtype. This cast would fail unless T implements IFilterable, but since we already checked that, we know that it will.
if (typeof(IMyInterface).IsAssignableFrom(typeof(T))
This checks whether a variable of type IMyInterface can be assigned from an instance of type T.
If you have a generic-type parameter that may or may not implement IFoo, it's possible to as cast it to a storage location of type IFoo; if you do that, you may pass it to any method which expects an IFoo, as well as any method that expects a generic parameter constrained to IFoo, but you will lose all generic type information if you do that--the parameter will be passed as type IFoo. Among other things, this will mean that if your original object was a structure, it will be boxed.
If you wish to test whether a generic parameter type implements IFoo and call a method that takes a generic-constrained IFoo if it does, while keeping the original generic type (this could be useful if the type is a struct, and could be necessary if the type is being passed to a generic method which has both IFoo and IBar constraints and the things one might want to pass do not share any single common supertype), it will be necessary to use Reflection.
For example, suppose one wants to have a method Zap which takes a generic ref parameter, calls Dispose on it if it implements IDisposable, and clears it out. If the parameter is an IDisposable class type, a null test should be performed as an atomic operation with clearing out the parameter.
public static class MaybeDisposer
{
static class ClassDisposer<T> where T : class,IDisposable
{
public static void Zap(ref T it)
{
T old_it = System.Threading.Interlocked.Exchange(ref it, null);
if (old_it != null)
{
Console.WriteLine("Disposing class {0}", typeof(T));
old_it.Dispose();
}
else
Console.WriteLine("Class ref {0} already null", typeof(T));
}
}
static class StructDisposer<T> where T : struct,IDisposable
{
public static void Zap(ref T it)
{
Console.WriteLine("Disposing struct {0}", typeof(T));
it.Dispose();
it = default(T);
}
}
static class nonDisposer<T>
{
public static void Zap(ref T it)
{
Console.WriteLine("Type {0} is not disposable", typeof(T));
it = default(T);
}
}
class findDisposer<T>
{
public static ActByRef<T> Zap = InitZap;
public static void InitZap(ref T it)
{
Type[] types = {typeof(T)};
Type t;
if (!(typeof(IDisposable).IsAssignableFrom(typeof(T))))
t = typeof(MaybeDisposer.nonDisposer<>).MakeGenericType(types);
else if (typeof(T).IsValueType)
t = typeof(MaybeDisposer.StructDisposer<>).MakeGenericType(types);
else
t = typeof(MaybeDisposer.ClassDisposer<>).MakeGenericType(types);
Console.WriteLine("Assigning disposer {0}", t);
Zap = (ActByRef<T>)Delegate.CreateDelegate(typeof(ActByRef<T>), t, "Zap");
Zap(ref it);
}
}
public static void Zap<T>(ref T it)
{
findDisposer<T>.Zap(ref it);
}
}
The first time the code is invoked with any type T, it will determine what sort of generic static class can be produced for that parameter and use Reflection to create a delegate to call a static method of that generic class. Subsequent calls with the same type T will use the cached delegate. Even though Reflection can be a little slow, it will only need to be used once for any type T. All subsequent calls to MaybeDisposer.Zap<T>(ref T it) with the same type T will be dispatched directly through the delegate and will thus execute quickly.
Note that the calls to MakeGenericType will throw exceptions if they are given generic type parameters which do not meet the constraints of the given open generic classes (e.g. if T was a class or did not implement IDisposable, an attempt to make the generic type StructDisposer<T> would throw an exception); such tests occur at run-time and are not validated by the compiler, so you can use run-time checking to see if the types meet appropriate constraints. Note that the code does not test whether it implements IDisposable, but instead tests whether T does. This is very important. Otherwise, if MaybeDispose was called with a parameter of type Object which held a reference to a Stream, it would determine that it implemented IDisposable and thus try to create a ClassDisposer<Object>, crashing because Object does not implement IDisposable.
The simplest form I can come up with is something like:
public IEnumerable<T> GetRecords()
{
IQueryable<T> entities = new List<T>().AsQueryable();
if (typeof(IFilterable).IsAssignableFrom(typeof(T)))
{
entities = FilterMe<IFilterable, T>(entities.OfType<IFilterable>()).AsQueryable();
}
return entities;
}
public IEnumerable<TResult> FilterMe<TSource, TResult>(IEnumerable<TSource> linked) where TSource : IFilterable
{
return linked.Where(r => true).OfType<TResult>();
}
The point here is the need to have types to pass into and get back out of the method. I had to change the types locally to get it working.
OfType will silently filter out items that are not really of a given type, so it assumes that it's a collection of the same type in any one call.
Because you are re-assigning from FilterMe, you still need the interface assignable check.
Is the OfType(...) method (link) what you're looking for?
public class MyModel<T> : IModel<T> where T : MyObjectBase
{
public IQueryable<T> GetRecords()
{
var entities = Repository.Query<T>();
if (typeof(IFilterable).IsAssignableFrom(typeof(T)))
{
//Filterme is a method that takes in IEnumerable<IFilterable>
entities = FilterMe(entities));
}
return entities;
}
public IEnumerable<TResult> FilterMe<TResult>(IEnumerable<TResult> linked) where TResult : IFilterable
{
var dict = GetDict();
return linked.OfType<TResult>().Where(r => dict.ContainsKey(r.Id));
}
}
In my answer, I assume that method FilterMe is used internally and should not be visible outside your model and could be marked private. If my assumption is wrong, you could create a private overload of FilterMe.
In my answer I just removed the generic <TResult>. I assume that this FilterMe always is about then entities of type T (since it is in the same Model class). This solves the problem about casting between T and TResult. TResult does not have to be marked as IFilterable since none of the members of IFilterable are used. And since the code already checks if T is IFilterable why check again (especially when FilterMe would be private)?
public IQueryable<T> GetRecords()
{
var entities = Repository.Query<T>();
if (typeof(IFilterable).IsAssignableFrom(typeof(T)))
{
//Filterme is a method that takes in IEnumerable<IFilterable>
entities = FilterMe(entities).AsQueryable();
}
return entities;
}
public IEnumerable<T> FilterMe(IEnumerable<T> linked)
{
var dict = GetDict();
return linked.Where(r => dict.ContainsKey(r.Id));
}
If you would create a second FilterMe, replace the IEumerable<T> types with Queryable<T>, so you do not have to convert your entities with AsQueryable().
public IEnumerable<TResult> FilterMe<TResult>(IEnumerable<TResult> linked) where TResult : IFilterable
{
var dict = GetDict();
return linked.Where(r => dict.ContainsKey(r.Id));
}
Try replacing FilterMe with this version:
public IEnumerable<T> FilterMe(IEnumerable<IFilterable> linked)
{
var dict = GetDict();
return linked.Where(r => dict.ContainsKey(r.Id)).Cast<T>();
}
Then, were you call, change your code to this:
if (typeof(IFilterable).IsAssignableFrom(typeof(T)))
{
//Filterme is a method that takes in IEnumerable<IFilterable>
var filterable = entities.Cast<IFilterable>();
entities = FilterMe(entities).AsQueryable();
}
You don't have to make the FilterMe method a generic method to achieve the same result.
public class MyModel<T> : IModel<T> where T : MyObjectBase {
public IQueryable<T> GetRecords()
{
var entities = Repository.Query<T>();
if (typeof(IFilterable).IsAssignableFrom(typeof(T)))
{
//Filterme is a method that takes in IEnumerable<IFilterable>
entities = FilterMe(entities.Cast<IFilterable>());
}
return entities;
}
public IEnumerable<T> FilterMe(IEnumerable<IFilterable> linked) {
var dict = GetDict();
return linked
.Where(r => dict.ContainsKey(r.Id))
.Cast<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. =)