c# – 在运行时创建继承抽象类并实现接口的类型

我们的架构广泛使用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有一个很好的tutorial,而Reflection.Emit类的文档可以在here找到.

转载注明原文:c# – 在运行时创建继承抽象类并实现接口的类型 - 代码日志