【问题标题】:create a dynamic class which overrides another class in C# / .Net在 C# / .Net 中创建一个覆盖另一个类的动态类
【发布时间】:2014-03-21 14:56:22
【问题描述】:

我不想“允许”在代码中直接创建对象,例如:

var p = new Product();

原因是我希望它由 IOC 控制,因此我可以轻松更改其实现或扩展它。因此,代码看起来像:

var p = iocContainer.Get<Product>();

问题是人们可能“忘记”致电 IOC,而转而使用 new 产品。我的想法是让Product 成为abstract 类。然后,动态创建一个类型说ProductImpl,它扩展自Product,它不是抽象的。在应用程序启动时,会扫描所有数据对象并自动创建这些动态类。这可能吗?理想情况下,这种类型的命名空间总是相同的,比如BusinessLogic.Impl.ProductImpl

创建的动态类将类似于以下内容:

public class ProductImpl : Product  
{
      public ProductImpl()
      {

      }

}

【问题讨论】:

  • 为什么不简单地将构造函数设为私有?
  • 当我需要它时,我怎样才能真正创建它?另外,我使用 RavenDB(文档数据库)作为我的数据存储,我不认为它可以在从数据存储加载回时使用私有构造函数重新创建对象。不过,我会调查一下。
  • 它可以通过使用反射的代码来工作,RavenDB 也支持它! :) 感谢您的快速回答。如果您将此作为答案发布,我可以将其标记为答案。
  • Activator.CreateInstance 具有允许使用非公共 ctor 创建对象的重载。我不知道 RavenDB,但如果你能提供一个创建对象的工厂,它也可以在那里工作。

标签: c# dynamic reflection


【解决方案1】:

通常,对于 IOC,您应该使用接口而不是具体对象。然后,当需要接口实现时,IOC 容器会创建相应的对象。

转而绕过IProduct 接口。如果您担心人们对其进行更新,IOC 可以随心所欲地调用实现对象。如果您真的很担心,您甚至可以将它们放在带有内部构造函数的单独程序集中。

【讨论】:

  • 其实我不会直接使用IOC,那只是为了让它更简单。我将通过 IOC 获得一个IDataObjectFactory,然后它可以创建任何对象。
【解决方案2】:

使用私有构造函数代替抽象类。

许多 IoC 容器都支持这一点(或可以扩展到)。此外,Activator.CreateInstance 具有允许使用非公共构造函数创建对象的重载。

【讨论】:

    【解决方案3】:

    您可以将构造函数设为私有并通过反射实例化类(请参阅this answer)。 或者,您可以通过使用接口及其实现来实现您描述的模式 - 我认为这比使用抽象类更好

    public interface IProduct {...}
    public class ProductImpl : IProduct {...}
    

    然后使用 IoC 实例化实现类,但返回接口。在这种情况下,缺点是您必须记住始终使用接口而不是类。

    另外,我认为根据您使用的 IoC 框架,可以使用私有构造函数来实例化类。

    更新

    更优雅的解决方案是将实现类移动到解决方案中的单独项目,并将构造函数声明为internal。我在一个项目中使用了这种方法,将 Unity 作为 IoC 框架。我在几个月前发布的question 中描述了它的架构,以及一些您可以阅读并用于您的案例的代码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-02
      相关资源
      最近更新 更多