【问题标题】:Simple Factory with reflection C#带有反射 C# 的简单工厂
【发布时间】:2015-05-21 14:13:24
【问题描述】:

使用反射的简单工厂包括在哈希表中存储(注册)各种类型名称及其对应的类类型,然后使用此哈希表在工厂中生成对象。

interface Product
{
    void foo();
}
class ProductFactory
{
    HashTable m_RegisteredProducts = new HashTable();
    public void registerProduct(string productID, Type p)    {
        m_RegisteredProducts.add(productID, p);
    }

    public Product createProduct(string productID){
        return (Product) new m_RegisteredProducts[productID];
    }
}

我不清楚注册新类型的过程何时发生,因为要使用的所有类型都将在运行时加载到哈希表中。在哪里调用 registerProduct()?

  1. 在 ProductFactory 类的一个地方为所有不同的类调用 registerProduct() 没有意义,因为它会破坏使用反射而不是简单的 switch/case 方法的目的。
  2. 如果在实现接口的所有类的类定义中调用 registerProduct(),则在 在/使用工厂之后创建该类的实例,因此总是会出错。

【问题讨论】:

  • 工厂应该生产实例。不应该采取实例(就像你正在做的那样)。
  • 这是一个伪代码,感谢您指出混淆。我会做出改变。
  • 您使用的是简单工厂,也就是具体工厂,而不是工厂方法模式。看看stackoverflow.com/questions/26511823/… 的区别简单工厂并不是真正的设计模式(它是一种编程习惯),也绝对不是factory-pattern,因为没有“子类决定要实例化哪个类”。

标签: c# design-patterns factory


【解决方案1】:

您的代码不会进行反射,因为它期望实现Product 接口的实例,而不是类型。您需要addProduct 来获取Type 实例,检查它是否实现Product 接口,然后在createProduct 中动态创建它的实例(使用type.GetConstructor(<constructor signature>).Invoke(<arguments>); 之类的东西)

这是我很久以前写的一篇类似的文章:http://blixt.org/2009/06/05/getting-types-implementing-class-or-interface

【讨论】:

    【解决方案2】:
    1. 在 ProductFactory 类的一个地方为所有不同的类调用 registerProduct() 没有意义,因为它会破坏使用反射而不是简单的 switch/case 方法的目的。

    当将扩展产品类添加到某个位置(例如插件目录)时,反射很有用。您有一个字符串列表来识别支持的插件,这些插件可以在文本文件中定义(应用程序属性,提供额外的安全层)或通过(通过反射)扫描所述插件目录(如果有人可以将被黑的产品放在那里)。免责声明:我从未在 C# 中这样做过,但它在 Java 中运行良好。除了新的产品代码和最终修改属性文件外,没有对应用程序代码进行修改。

    1. 如果在实现该接口的所有类的类定义中调用 registerProduct(),则该类的实例是在/使用 Factory 之后创建的,因此总是会出错。

    我不确定这始终是您问题中代码的策略(它来自哪里?)。你可能想在http://www.codeproject.com/Articles/37547/Exploring-Factory-Pattern阅读更多关于反射与简单工厂结合的不同策略

    【讨论】:

      【解决方案3】:

      这取决于。不同的场景需要不同的策略。 如果所有产品类型都在同一个程序集(或程序集列表)中定义,我经常看到一种策略,您可以这样调用:

      var productTypes= from t in Assembly.GetExecutingAssembly().GetTypes()
                        where t.GetInterfaces().Contains(typeof(IProduct));
      

      然后为 productTypes 中的每个元素调用 registerProduct()。

      【讨论】:

      • 这是我在my answer中提到的“扫描插件目录”并注册的代码。
      猜你喜欢
      • 2011-11-04
      • 2020-06-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多