简单的工厂用反射C#

时间:2015-05-21 14:13:25

标签: c# design-patterns factory

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

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(),则在/使用之后创建类的实例,因此总是会出错。

3 个答案:

答案 0 :(得分:0)

您的代码没有进行反思,因为它期望实例实现Product接口,而不是类型。您需要addProduct来获取Type实例,检查它是否实现了Product接口,然后在createProduct中动态创建它的实例(使用{{1}之类的内容})

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

答案 1 :(得分:0)

  
      
  1. 在ProductFactory类中的单个位置为所有不同的类调用registerProduct()没有意义,因为它会破坏使用反射而不是天真的switch / case方法的目的。
  2.   

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

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

我不确定问题中的代码策略是什么(它来自哪里?)。您可能希望在http://www.codeproject.com/Articles/37547/Exploring-Factory-Pattern

中阅读更多有关不同反射策略和简单工厂的信息

答案 2 :(得分:0)

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

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

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