[英]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.