instantiate a class implementing a generic interface using reflection - c#

I have the following in a business logic assembly:
public class BusinessEntity
{
...
}
public class Customer : BusinessEntity
{
...
}
public interface IEntityManager <T> where T : BusinessEntity
{
T SaveData(T oData);
}
public CustomerEntityManager : IEntityManager <Customer>
{
Customer SaveData(Customer o)
{
...
}
}
I am forced to load the above assembly (due to a couple of obvious reasons) in my current project through reflection and instantiate CustomersEntityManager. Imagine that I am writing a method as follows:
public class EntityFactory
{
public static IEntityManager<BusinessEntity> GetManagerInstance(string EntityName)
{
var asm = GetAssembly(); // imagine that I loaded the assembly somehow
EntityName = "Customer"; // just imagine
object o;
// DO NOT KNOW WHAT TO WRITE HERE.
return o as IEntityManager<BusinessEntity>; // this needs to be an instance of CustomerEntityManager.
}
}
I have the option to modify business assembly. But the instance creation needs to be in my current project and I have to load the business assembly using reflection. All the data types will be known only at run-time.
I may be missing some fundamental things or probably doing wrong coding. Please help me out on this.
UPDATE:
Followed "driss" suggestion, like following:
string fullTypeName = "Your.Namespace." + EntityName + "EntityManager";
object o = Activator.CreateInstance(asm.FullName, fullTypeName);
Looks like it created the instance. However, it ended up with an error:
Cannot cast 'o' (which has an actual type of 'CustomerEntityManager') to 'IEntityManager'
when the following statement is getting executed:
return o as IEntityManager<BusinessEntity>
Thanks

You need to construct the full type name somehow, so that you can get the Type instance representing the type. You might decide that the type name relies on a convention, such that you could find the full type name as:
string fullTypeName = "Your.Namespace." + EntityName + "EntityManager";
object o = Activator.CreateInstance(asm.FullName, fullTypeName);
Then it is just a matter of calling Activator.CreateInstance, as you see.
However, I would highly recommend you looking into using an IoC framework for solving this problem.
Re: your comment:
You can't cast CustomerEntityManager to IEntityManager, because that is not what it implements - it only implements IEntityManager. If the cast was allowed, type safety would be broken (you could pass in a BusinessEntity, when the implementation clearly expects a Customer, or, that is at least what the contract says. (Co/contra variance can't save you here because T goes both in and out of IEntityManager).

Forget about using low-level reflection at your own, a lot of not very convenient work. Use an IoC framework if you can, i.e. StructureMap. With StructureMap you'll just need to create a Registry that knows all the dependencies (such as CustomersEntityManager is our implementation for IEntityManager<Customer>). It looks more less like that:
For<IEntityManager<Customer>>().Use<CustomersEntityManager>()
And now if you ask your StructureMap container for an implementation of IEntityManager<Customer>, you'll get CustomersEntityManager:
ObjectFactory.GetInstance<IEntityManager<Customer>>(); // will return instance of CustomersEntityManager
If you don't know the requested type at compile time, you can ask for the entity manager using plain Type instance:
string entityName = "Customer";
Type entityType = Type.GetType(entityType);
Type requestedType = typeof(IEntityManager<>).MakeGenericType(new[] { entityType });
ObjectFactory.GetInstance(requestedType); // will also return CustomersEntityManager instance
Registry can be defined in your assembly, without touching the business assembly.

Checkout Activator.CreateInstance()
Object o = Activator.CreateInstance (asm.FullName, EntityName );
will give you an instance of the Customer. I'm not sure how you would go from Customer to CustomerEntity but I'm sure you can work that part out.

Related

Factory Pattern, selecting by Property

I have a (growing) list of Data-Generators. The generator that I need is created by a factory class. The generators all implement a common Interface, which includes among other things a static string name.
What I would like to do: Call the factory.Create method with a string parameter for the above mentioned name. The create method finds the generator with this name and returns a new instance of said generator.
Bonus in my opinion of this way to do it: I only have to add new generator classes without having to edit the factory.
Question:
Is this a good way to handle this problem?
How can I find all generators? Reflection over every implementation of the interface/every member of the namespace (unique for the generators + their interface)?
Is it correct to call this way of working a factory, or is this some different pattern?
In the end I would call the factory like this (simplified):
//Caller
public DataModel GetData2()
{
var generator = new DataFactory().Create("Gen.2");
return generator.GetData();
}
//Factory
public class DataFactory
{
public AbstractDataGenerator Create(string type)
{
//Here the magic happens to find all implementations of IDataGenerator
var allGenerators = GetImplementations();
var generator = allGenerators.FirstOrDefault(f => f.name == type);
if (generator != null)
return (AbstractDataGenerator)Activator.CreateInstance(generator);
else
return null;
}
}
//Interface
public abstract class AbstractDataGenerator
{
public static string name;
public abstract DataModel GetData();
}
//Data-Generators
public class DataGen1 : AbstractDataGenerator
{
public static string name = "Gen.1";
public DataModel GetData()
{
return new DataModel("1");
}
}
public class DataGen2 : AbstractDataGenerator
{
public static string name = "Gen.2";
public DataModel GetData()
{
return new DataModel("2");
}
}
Should the magic GetImplementations() in the factory be done via Reflection or somehow different? Should I use a completely different approach?
Since answers refer to IoC and DI: This project uses NInject already, so it would be available.
Switched from interface to abstract class.
Is this a good way to handle this problem?
Having a factory to get an instance of the logic class you need by some key - I believe it is a good way. It is a pattern that I use a lot myself. About the way you have your key - I'd prefer to not have it as a static member (regardless to the fact that interfaces can't have static members) but just as a property and to add a base class to the IDataGenerator. That base class will have a constructor that will get the name - That way each new DataGenerator you create will have to set it and you wont forget.
About having the name as a string - I personally prefer having it "strongly typed". What I mean is that if I pass Gen . 2 instead of Gen.2 with strings I will discover this problem only in runtime. Possible other ways (if you want, because a simple string is fine too - a matter of taste):
Replace strings with an enum
Have a static class with static readonly strings for all your values - then in your code use those values. You get the benifits of the intellisense and of not getting the string wrong but better than enum - you can just still pass strings that are not in the "list" so you can add new ones as add-ons.
Have a RequestGenerator object, with each Generator being IDataGenerator<TGeneratorRequest>. This might be an overkill but if you have also extra information you need for the creating of a DataGenerator which differs between them then consider it .
How can I find all generators? Reflection over every implementation of the interface/every member of the namespace (unique for the generators + their interface)?
Yes, reflection can be a good way to do so. However, I would suggest to read into Dependency Injection and IoC Containers like Castle Windsor for example. There are things out there that already implement it for you, so why to re-invent the wheel :)
DI is a life changer concept in my opinion
Is it correct to call this way of working a factory, or is this some different pattern?
Yap. It is a Factory
Should the magic GetImplementations() in the factory be done via Reflection or somehow different?
See answer for question 2
This is where constructor injection can REALLY shine. Look into dependency injection tools and employ one! It also checks your "Bonus" request.
Here's what your factory might look like with constructor injection:
public class DataFactory
{
private Dictionary<string, IDataGenerator> generators;
public DataFactory(IDataGenerator[] generatorReferences)
{
this.generators = generatorReferences
.ToDictionary(k => k.name, v => v);
}
public IDataGenerator Create(string type)
{
IDataGenerator generator = null;
this.generators.TryGetValue(type, out generator);
return generator;
}
}
Most DI software has the capability to automatically scan assemblies for implementations of a certain type (e.g. IDataGenerator) and register those with itself, when it constructs an instance of your DataFactory it'll automatically include them.

How can I change a type's attributes?

How can I modify the TypeAttributes attached to a certain Type?
I want to modify a type and make it abstract by applying the TypeAttributes.Abstract flag, how can I do this?
I'm sure I need to call into the CLR somewhere, but I can't trace down where it gets this info from, it seems to be an endless system of layered methods calling other ones.
You can alter a type programatically using a library such as Mono.Cecil.
Assume you have a class named "Test" in an assembly named "ExistingAssembly.dll" and you wish to turn the class "Test" into an abstract class.
All you now need to do is:
void Main(){
//This is the existing assembly containing the type that you wish to modify
var assemblyFile = #"C:\temp\ExistingAssembly.dll";
var ass = Mono.Cecil.AssemblyDefinition.ReadAssembly(assemblyFile);
var type = ass.MainModule.GetTypes().First(t => t.Name == "Test");
//Make the type an Abstract type (class)
type.IsAbstract = true;
//Finally save the modified assembly into a new file
ass.Write(#"C:\temp\ModifiedAssembly.dll");
//The type "Test" in the above "ModifiedAssembly.dll" is now an abstract class.
}
// This is the Type that you wish to turn into an Abstract Class
public class Test {
public string DummyMethod(){
return "Dummy Return";
}
}
You can get the Mono.Cecil assembly from here (Nuget):
https://www.nuget.org/packages/Mono.Cecil/

How to discover the underlying Implementation Type of a decorated instance when calling GetAllInstances?

I have this code:
using (container.BeginLifetimeScope())
{
RenderWord instruction = new RenderWord();
var instances = container.GetAllInstances<IInstructionHandler<RenderWord>>();
var firstInstance = result.First();
}
instances is of type IEnumerable<IInstructionHandler<RenderWord>>
firstInstance is of type IInstructionHandler<RenderWord> that in reality is an instance of a decorator that decorates another decorator that decorates another decorator ...
At runtime the actual class instances is of type ContainerControlledCollection<IInstructionHandler<RenderWord>> and this ContainerControlledCollection class holds a very useful piece of information - the underlying ImplementationType.
Is there any way for me to get to the ContainerControlledCollection or the producers[0].Value.ImplementationType at runtime because I’d really like to be able to discover the base implementation type underneath the chain of decorators.
I think #atomaras might have a good point about your abstraction, although I think it would be fine when you only use this information inside your Composition Root, since your Composition Root is already aware of every implementation in the system.
I think there are a few ways to get to this information:
Use the DecoratorPredicateContext information that is supplied to the RegisterDecorator extension method:
var typeMapping = new Dictionary<Type, Type>();
container.RegisterDecorator(typeof(IInstructionHandler<>), typeof(FakeDecorator<>), c =>
{
typeMapping[c.ServiceType] = c.ImplementationType;
// or perhaps even use c.AppliedDecorators property to see which decorators
// are applied.
// return false to prevent the decorator from being applied.
return false;
});
You can make a fake registration that Simple Injector will call for every IInstructionHandler<T> in the system, but you prevent it from being applied by supplying a predicate that will always return false. You can use the info supplied by Simple Injector in the DecoratorPredicateContext to find out what the actual ImplementationType is.
Alternatively, you can inject an DecoratorContext instance (v2.6 and up) into the top most decorator (as explained here). The DecoratorContext contains the same information as the DecoratorPredicateContext does, but this object will automatically be injected by Simple Injector into a decorator that depends on. It allows you to make the decision inside a decorator, which might be very convenient in your case.
Add an an IDecorator abstraction to the system to allow traversing the decorator chain.
By letting each decorator implement a IDecorator interface that allows access to the decoratee (just as done here) you can traverse the decorator chain and find the actual implementation type:
public interface IDecorator
{
object Decoratee { get; }
}
public static class DecoratorHelpers
{
public static IEnumerable<object> GetDecoratorChain(IDecorator decorator)
{
while (decorator != null)
{
yield return decorator;
decorator = decorator.Decoratee as IDecorator;
}
}
}
You can implement your decorators with this interface as follows:
public class SomeDecorator<T> : IInstructionHandler<T>, IDecorator
{
private readonly IInstructionHandler<T> decoratee;
public SomeDecorator(IInstructionHandler<T> decoratee)
{
this.decoratee = decoratee;
}
object IDecorator.Decoratee { get { return this.decoratee; } }
}
When you implemented this interface on all your decorators, you will be able to do this:
var implementationTypes =
from handler in container.GetAllInstances<IInstructionHandler<RenderWord>>()
let mostInnerDecorator =
DecoratorHelpers.GetDecoratorChain(handler as IDecorator).LastOrDefault()
let implementation = mostInnerDecorator != null ? mostInnerDecorator.Decoratee : handler
select implementation.GetType()
Register a list of Registration instances in one of the RegisterAll overloads, since the Registration object knows about the actual implemenation type.
But instead of point 3, you might as well use the list of implemenation types that you used to create those registrations:
typeMapping[serviceType] = implementationTypes;
container.RegisterAll(serviceType, implementationTypes);
Simple Injector will resolve the registered implementations always in the same order as they are registered (this is guaranteed). So when you resolve a collection of things, you will already have the list of implementations that is layed out in the same order.
Why dont you just check the type of the firstInstance? Wouldn't that give you the actual implementation type?
I have to say though that the fact that you need to know the implementation type is a good indication of problems with your abstraction.

Autofac: how to inject properties with dynamic values?

By Autofac, it's easy to inject a static value to the CurrentDate property to instances of classes in a given assembly:
builder.RegisterApiControllers(asm).WithProperty("CurrentDate", new DateTime(2012, 1, 13));
However, how to inject dynamic values e.g. values returned by a lamda () => { return DateTime.Now; } to the CurrentDate property?
Sounds like you could use pretty standard property injection, like this:
builder.RegisterApiControllers(asm)
.OnActivating(e => { e.Instance.CurrentDate = DateTime.Now; });
Note that you may need to cast e.Instance as it will probably be of type Object.
See Lifetime Events in the documentation for more info.
On second thought, why not just put the initialization in the base class constructor?
public DateTime CurrentDate { get; private set; }
protected ApiController() { CurrentDate = DateTime.Now; }
The current date isn't really a dependency you need a DI container to provide.
Register another service that provides your dynamic values (e.g. IDateTimeService) [I assume it's really something more complex than a DateTime that you want.] The default lifetime for this new service will be Instance per dependency but you could use "Per Matching Lifetime Scope". Your Controllers will already be created per Http request.
Now simply add a dependency from your controllers on the IDateTimeService (in the constructor). In the methods within that controller you can now get hold of the dynamic value you want from that service.
private static readonly IDateTimeService datetimeService;
public MyController (IDateTimeService datetimeService)
{
this.datetimeService = datetimeService;
}
public void SomeMethod()
{
var date = datetimeService.GetDate();
...
}
You need to write custom parameter like this:
public class DelegateParameter : Parameter
{
private readonly string _name;
private readonly Func<object> _getValue;
public DelegateParameter(string name, Func<object> getValue)
{
if (name == null) throw new ArgumentNullException("name");
if (getValue == null) throw new ArgumentNullException("getValue");
_name = name;
_getValue = getValue;
}
public override bool CanSupplyValue(ParameterInfo pi, IComponentContext context, out Func<object> valueProvider)
{
PropertyInfo propertyInfo = GetProperty(pi);
if (propertyInfo == null || propertyInfo.Name != _name)
{
valueProvider = null;
return false;
}
valueProvider = _getValue;
return true;
}
private static PropertyInfo GetProperty(ParameterInfo pi)
{
var methodInfo = pi.Member as MethodInfo;
if (methodInfo != null && methodInfo.IsSpecialName && (methodInfo.Name.StartsWith("set_", StringComparison.Ordinal) && methodInfo.DeclaringType != null))
return methodInfo.DeclaringType.GetProperty(methodInfo.Name.Substring(4));
return null;
}
}
And then use it:
builder.RegisterApiControllers(asm).WithProperty(new DelegateParameter("CurrentDate", () => DateTime.Now));
If you are trying to inject the lambda expression, rather than the result of the lambda expression, you have quite a few imperfect options. Here are just a few; I'm sure that there are more.
Autofac
The Autofac wiki on Google Project Hosting documents four ways of injecting properties. Three of them appear to use constant or default values--you mentioned one of these methods.
The final seems to give the developer a bit more control over properties. It uses the OnActivating event, during which you have a few options. You could:
Set the property and hope it sticks.
If the property lacks an accessible setter, you could use reflection to set it, or its backing property (by default, m_PropertyName for a property named PropertyName, if I recall correctly).
Wrap the instance in a proxy, as they put it: see Polymorphism below.
Polymorphism
Let ClassA contain the property to be modified, Prop1. Create a new class ClassB that extends ClassA. If Prop1 has a virtual modifier, you can override it. Otherwise, use the new modifier to create a similar property in ClassB containing your dynamic code.
In the case of an override, you will need to instantiate ClassB in place of ClassA. This will not work if the framework creates its own instances of ClassA, but as long as you create your own instances of ClassB and pass them to the framework, you should be good to go.
If you are using a new property, in addition to instantiating ClassB, you also have to ensure that whenever you access the new property, the object is cast to ClassB or a descendant type. This generally will not work if another framework is designed to use ClassA, since it will always operate on type ClassA, not ClassB, regardless of your casting.
Bytecode Manipulation
This is nasty stuff, but it will do exactly what you want. C# generally compiles to an assembly/bytecode language called CIL. Microsoft's variant is MSIL, but it's pretty much identical to generic CIL.
I've always used Mono.Cecil for CLI/CLR (.NET, Mono) bytecode manipulation. It seems to work flawlessly, and it's quite nice once you get the hang of it. However, you have to know two things:
How to use CIL
How to use Mono.Cecil
The first one isn't that bad. A few Wikipedia pages with detailed tables are all that you need, provided that you have sufficient experience with CLI. If you think CLI stands for nothing other than "command line interface", then you might run into difficulty.
Mono.Cecil, on the other hand, lacked any form of proper documentation as of about a year ago (2012). The learning curve was impossibly steep. I had a miserable few days trying to figure it out. It's amazing when it works, though.

Create and use an instance of an class who's class name is only known at runtime

I have a list of class names and methods that can only be read during runtime. Is it possible to create a class dynamically like that? I'm currently using C# 4.0.
It is a little unclear whether you want to define a type at runtime and define methods against it, or whether you want to create an instance of an already-written type, and call methods on it.
Fortunately both are possible.
The second scenario is more likely, so you'd want to look at reflection (below) - but note that there are performance penalties associate with this (and small things like "what arguments does the method take" become very important).
For the first scenario, you'd need to look at TypeBuilder, but that is much more complex. Another option would be CSharpCodeProvider and dynamic assembly loading, but again - not trivial by any stretch.
using System;
namespace MyNamespace {
public class Foo {
public void Bar() {
Console.WriteLine("Foo.Bar called");
}
}
}
class Program {
static void Main() {
string className = "MyNamespace.Foo, MyAssemblyName",
methodName = "Bar";
Type type = Type.GetType(className);
object obj = Activator.CreateInstance(type);
type.GetMethod(methodName).Invoke(obj, null);
}
}
To include parameters (comments) you pass an object[] instead of the null:
using System;
namespace MyNamespace {
public class Foo {
public void Bar(string value) {
Console.WriteLine("Foo.Bar called: " + value);
}
}
}
class Program {
static void Main() {
string className = "MyNamespace.Foo, MyAssemblyName",
methodName = "Bar";
Type type = Type.GetType(className);
object obj = Activator.CreateInstance(type);
object[] args = { "hello, world" };
type.GetMethod(methodName).Invoke(obj, args);
}
}
If you are doing this lots (for the same method) there is a way to improve performance via a typed delegate, but this doesn't gain you much for occasional calls.
You can use the IL emit functionality straight out of the .Net framework to accomplish this. You will need to learn IL in order to dynamically generate type information at runtime--this is not for the feint of heart.
Introduction to Creating Dynamic Types with System.Reflection.Emit
As I can't really answer that you are asking I will answer a number of question you might want to ask.
Can I create an instance of class and call its method where both class and method are specified at run time?
Sure. The simple way first. Use a if statements:
var className = "MyClass";
var methodName = "MyMethod";
if (className == typeof(MyClass).Name) {
var instance = new MyClass();
if (methodName == "MyMethod")
instance.MyMethod();
if (methodName == "MyOtherMethod")
instance.MyOtherMethod();
}
Alternatively, you can use Activator.CreateInstance to create an instance of a class for you.
var className = "MyClass";
var methodName = "MyMethod";
//Get a reference to the Assembly that has the desired class. Assume that all classes that we dynamically invoke are in the same assembly as MyClass.
var assembly = typeof(MyClass).Assembly;
//Find the type that we want to create
var type = assembly.GetTypes().FirstOrDefault(t=>t.Name == className);
if(type != null) {
//Create an instance of this type.
var instance = Activator.CreateInstance(type);
//Find the method and call it.
instance.GetType().GetMethod(methodName).Invoke(instance);
}
Can I generate a class at run time?
Yes you can but it's hard. If you are an experienced C# programmer, know a bit of C++ and assembly, you should be able to grock it. If not, don't bother.
Microsoft provides a library to emit Intermediate Language code called, surpose, IL.Emit. There are very few problems that warrant using this method, amongst those are mock object generation and some aspects of Dependency Injection. It is quite likely that your problem is better solved in another fashion.

Categories

Resources