开发者

instantiate a class implementing a generic interface using reflection

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 "dris开发者_开发知识库s" 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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜