[英]Create type at runtime that inherits an abstract class and implements an interface
我们的架构广泛使用Repository模式。 我们有大多数存储库的抽象基类,它们实现了一些常用功能(例如get,load,list等)。 这个基类IRepository有一个相应的接口,它定义了抽象类的公共方法。 大多数实体都有一个相应的存储库接口,例如,Foo实体有一个IFooRepository,后者又实现了IRepository。
我刚才描述的是相当典型的,虽然我知道它并非没有问题。 但无论如何,这是我们拥有的,我们必须忍受它。
我对这种类型的体系结构的宠爱之一就是必须定义简单地继承基本Repository类的空类,而不执行任何其他操作,例如:
public class FooRepository : Repository, IFooRepository
{
}
解决这个冗余代码的一种方法是允许我们的IOC框架在运行时动态创建这些类,这样我就不必自己编写它们了。 如果我可以弄清楚如何动态创建这些类,那么我已经知道将它们插入NInject的位置。
有谁知道一些可以创建这样一个类的代码? 也许这可以通过像Castle这样的代理框架来完成?
我对您提出的问题提出的可能性很感兴趣,因此我对如何使用Castle的DynamicProxy或Reflection.Emit类生成存储库代理进行了一些调查。
使用以下存储库和域类(我扩展了场景以允许存储库返回强类型集合):
public interface IRepository<T>
{
IEnumerable<T> All { get; }
}
public abstract class Repository<T> : IRepository<T>
{
public IEnumerable<T> All
{
get
{
return new T[0];
}
}
}
public interface IFooRepository : IRepository<Foo>
{
}
public class Foo
{
}
生成相当于的代理
public class FooRepository : Repository<Foo>, IFooRepository
{
}
使用DynamicProxy时:
DefaultProxyBuilder proxyBuilder = new DefaultProxyBuilder();
Type baseType = typeof(Repository<>).MakeGenericType(typeof(Foo));
Type[] intefacesImplemented = new Type[] { typeof(IFooRepository) };
Type proxy = proxyBuilder.CreateClassProxyType(baseType, intefacesImplemented, ProxyGenerationOptions.Default);
使用Reflection.Emit时:
Type baseType = typeof(Repository<>).MakeGenericType(typeof(Foo));
Type repositoryInteface = typeof(IFooRepository);
AssemblyName asmName = new AssemblyName(
string.Format("{0}_{1}", "tmpAsm", Guid.NewGuid().ToString("N"))
);
// create in memory assembly only
AssemblyBuilder asmBuilder =
AppDomain.CurrentDomain.DefineDynamicAssembly(asmName, AssemblyBuilderAccess.Run);
ModuleBuilder moduleBuilder =
asmBuilder.DefineDynamicModule("core");
string proxyTypeName = string.Format("{0}_{1}", repositoryInteface.Name, Guid.NewGuid().ToString("N"));
TypeBuilder typeBuilder =
moduleBuilder.DefineType(proxyTypeName);
typeBuilder.AddInterfaceImplementation(repositoryInteface);
typeBuilder.SetParent(baseType);
Type proxy = typeBuilder.CreateType();
然后,您可以将它们与您的IOC容器一起注册并像往常一样使用它们(在本例中为Windsor):
WindsorContainer container = new WindsorContainer();
container.Register(Component.For<IFooRepository>().Forward(proxy));
IFooRepository repository = container.Resolve<IFooRepository>();
IEnumerable<Foo> allFoos = repository.All;
可以设置Reflection.Emit和DynamicProxy,允许使用非默认构造函数。
如果您有兴趣,可以在DynamicProxy上找到一个很好的教程 ,而在这里可以找到Reflection.Emit类的文档。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.