簡體   English   中英

在運行時創建類型,繼承抽象類並實現接口

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

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM