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

2023-11-24

我们的架构广泛使用存储库模式。 我们为大多数存储库提供了一个抽象基类,它实现了一些常见的功能(例如获取、加载、列表等)。这个基类有一个对应的接口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
{
}

使用动态代理时:

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 都可以设置为允许使用非默认构造函数。

如果你有兴趣,这里有一个很棒的tutorial在 DynamicProxy 上,而 Reflection.Emit 类的文档可以找到here.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在运行时创建继承抽象类并实现接口的类型 的相关文章

随机推荐

  • Angular 12 升级问题:您可能需要适当的加载器来处理此文件类型,当前没有配置加载器来处理此文件

    我已从 Angular 11 升级到 12 每个 SVG 文件都出现以下错误 错误 模块解析失败 意外的标记 1 0 您可能需要适当的加载程序来处理此文件类型 目前没有配置加载程序来处理此文件 例如 SVG 文件
  • Java中创建数组时会调用Object构造函数吗?

    在 Java 中 数组是一个对象 我的问题是 创建新数组时是否调用对象构造函数 我们想利用这个事实来使用一些额外的字节码来检测对象构造函数 以检查正在构造的数组的长度 那行得通吗 Per the JVM spec 数组是使用一组不同的指令创
  • javax.faces.FacesException:无法解析 NavigationCase 的结果

    我有一个 template xhtml 文件 位于 template template xhtml
  • 单击按钮时从自定义列表视图中删除项目

    我有一个自定义列表视图 有 2 个文本视图和 2 个按钮 播放和删除按钮 我希望当我单击删除按钮时删除当前行 我的适配器类 import java util ArrayList import android content Context
  • 判断一个数是否是斐波那契数

    我需要编写一段Java代码来检查用户输入的数字是否在斐波那契数列中 我在将斐波那契数列写入输出时没有任何问题 但是 可能是因为已经是深夜了 我正在努力思考 是否 是斐波那契数列 我不断地一遍又一遍地开始 这真的让我很头疼 我目前拥有的是第n
  • 从 C 调用 FORTRAN 子例程

    我正在尝试从 C 调用 FORTRAN 函数 我的问题是 If fortRoutine是我的 Fortran 子例程的名称 那么我从 C 调用它 作为fortRoutine If fortRoutine仅包含一个字符数组参数 那么我可以这样
  • 山狮升级后无法安装某些宝石

    我刚刚将我的 Macbook 更新为 Mountain Lion 但现在我无法安装一些 gem 因为出现以下有关标头的错误 我环顾四周 这似乎与缺少 Ruby 标头有关 建议安装 Xcode 因此我从应用商店安装了完整的 Xcode 以及
  • android 两个应用程序之间的通信

    我需要一些帮助来开始开发两个相互通信的 Android 应用程序 在一部手机上 应用程序 A 向应用程序 B 发送字符串 应用程序 B 接收字符串 例如 startClassOne 应用程序 B 使用方法启动 classOne 并获取结果
  • 如何制作不区分大小写的ConcurrentMap?

    我该如何实施 class CaseInsensitiveConcurrentMap
  • 获取 2 个字符串之间的字符串

    如何获取位于两个其他声明的字符串之间的字符串 例如 String 1 STRING1 String 2 STRING2 Source 832h0ufhu0sdf4 STRING1 I need this text here STRING2
  • 你能以 O(n) 摊余复杂度对 n 个整数进行排序吗?

    理论上是否可以以 O n 的摊余复杂度对 n 个整数的数组进行排序 尝试创建 O n 复杂度的最坏情况怎么样 现在的大多数算法都是建立在平均 O nlogn 最坏情况 O n 2 之上 有些虽然使用更多内存 但最糟糕的是 O nlogn 你
  • 无法加载捆绑包中的 NIB

    我正在尝试将 Janrain Engage 作为自定义模块与 Appcelerator Titanium 集成 我创建了一个示例模块 并将 JREngage 文件夹拖到示例模块 xcodeproj 如 Jainrain 文档中所示 现在我给
  • Python 和 R 之间的线性回归系数之间的差异

    我正在尝试在 Python 中运行我已经在 R 中完成的线性回归 以便找到系数为 0 的变量 我遇到的问题是 R 中的线性回归返回低方差列的 NA 而 scikit learn 回归返回系数 在 R 代码中 我通过将带有 NA 的变量保存为
  • 从 python selenium 测试中制作 exe 文件

    我尝试在 exe 文件中构建 python selenium 测试 并在许多机器上运行它 以保持测试独立于环境 但结果 exe 文件找不到 selenium webdriver 如何在 exe 文件中包含所有硒依赖项 或者也许还有其他方法吗
  • 尝试将 R.exe 添加到 PATH

    所以我尝试将 R 添加到 Windows 10 上的路径 这应该很简单 System Properties gt Environment variables gt Edit gt new copy and paste C Program F
  • 为什么单击文本框会导致自动滚动面板滚动回顶部?

    在 C 应用程序中完成注册表单时 我注意到 如果我启用自动滚动 然后在滚动条下方有一个文本框 然后单击它 它会一直跳回到顶部 有没有办法用一些代码来解决这个问题 或者这是一个专有名词 对我来说用语言解释有点困难 所以这里是一个短视频这表明了
  • “shutdown -y”到底是做什么的? [关闭]

    Closed 这个问题不符合堆栈溢出指南 目前不接受答案 我在之后尝试了一些随机参数shutdown当我偶然发现 PowerShell 2 0 中的命令时shutdown y 所有这一切seems要做的就是注销用户 如果使用任何其他随机字母
  • python 中的泛型/模板?

    python 如何处理泛型 模板类型场景 假设我想创建一个外部文件 BinaryTree py 并让它处理二叉树 但适用于任何数据类型 所以我可以将自定义对象的类型传递给它 并拥有该对象的二叉树 这是如何在 python 中完成的 其他答案
  • 更改图钉颜色 MKMapView

    我以这种方式向地图添加注释 MyAnnotation annotationPoint2 MyAnnotation alloc init annotationPoint2 coordinate anyLocation annotationPo
  • 在运行时创建继承抽象类并实现接口的类型

    我们的架构广泛使用存储库模式 我们为大多数存储库提供了一个抽象基类 它实现了一些常见的功能 例如获取 加载 列表等 这个基类有一个对应的接口IRepository 它定义了抽象类的公共方法 大多数实体都有对应的存储库接口 例如Foo 实体有