c# - 使用反射的工厂模式 - 使用与每个类关联的静态键进行类注册

标签 c# reflection factory-pattern

在研究一些模式时,我遇到了工厂模式来创建(未知)类的实例。这让我很感兴趣,因此我想构建一个可以动态增强的程序。因此,我在一个程序集中具有一些基本功能,而在不同程序集中具有实际工作人员。我从应用程序中得到的唯一提示是操作名称。现在我想创建一个依赖操作的新worker。因为我不知道 worker 的实际实现,所以我选择了这种模式。

好的,更多细节:

我有一个 IWorker 接口(interface),我的所有进程都实现它。 Singleton WorkerFactory 允许我创建在与当前路径相同的任何程序集中实现的任何工作线程的新实例。为此,我在界面中添加了一个 CreateWorker 方法,该方法接受字符串数组(已作为 varargs 传递到控制台应用程序)。

在能够创建任何工作人员的任何实例之前,我必须向工厂注册任何类。不幸的是,在 C# 上,不可能将这样的行为静态地插入到工作类的任何静态上下文中,因为只有在以任何方式访问该类时(无论是通过实例化它还是通过访问任何其静态成员,请参阅 static constructors )。因此,我通过使用当前正在执行的程序集的路径反射(reflect)所有程序集中找到的所有类型来实现此目的。 现在我可以检查当前类型是否正在实现该接口(interface),如果是,则可以将类型添加到包含操作名称(键)和工作人员(值)的工厂的注册映射中,作为System.Type(参见Factory Pattern using reflection)。问题是:如何获取该类型引用的操作的实际名称。

我认为有两种选择:

  1. 我向每个存储操作名称的工作器类添加一个静态属性。因此,我可以通过在获取的类型上反射(reflect)此属性来引用该操作。
  2. 为名称添加非静态属性,并在注册时创建实际工作类的虚拟实例。

虽然前一个选项的缺点是我无法确保所有工作人员实际上都实现了这样的静态属性(因此不可能将静态成员添加到 IWorker 接口(interface)),但后者的缺点是每个类都必须有一个空的构造函数,以便构建从中获取操作名称的虚拟实例。尽管如此,这个构造函数将是可公开访问的,同时不包含任何初始化代码。

话虽如此,所有这些问题都是关于使用反射的工厂模式的最佳或至少更好的实践。我想我更喜欢第一个选择,但也许我也错过了这种方法的任何更好的解决方案。

因此,这个线程已经很长了,我不想在这里发布任何代码,但如果您需要,请告诉我。

最佳答案

您可以使用custom attributes在你的 worker 类(Class)上:

[AttributeUsage(System.AttributeTargets.Class)]
public class WorkerAttribute : Attribute
{
    public WorkerAttribute (String operationType)
    {
       this.OperationType = operationType; 
    }

    public String OperationType {get; private set;}
}

public interface IWorker { }

[WorkerAttribute("Experienced")]
public class ExperiencedWorker: IWorker
{
}

它们的访问方式与描述的一样here 。它会是这样的:

       Type attributeType = typeof(WorkerAttribute);

        var myWorkerClassesPlusAttributes = from assembly in AppDomain.CurrentDomain.GetAssemblies()
                                            from type in assembly.GetTypes()
                                            let attributes = type.GetCustomAttributes(attributeType, true)
                                            where attributes.Any()
                                            select 
                                                new KeyValuePair<String, Type>(((WorkerAttribute)attributes.First()).OperationType, 
                                                                               type);

        Dictionary<String, Type> workers = new Dictionary<string, Type>();
        foreach (var item in myWorkerClassesPlusAttributes)
            workers.Add(item.Key, item.Value);

        IWorker worker = (IWorker)Activator.CreateInstance(workers["Experienced"]);

它不是最好的,也没有涵盖类上的多个 WorkerAttributes,但可以用作您的解决方案的基础。

关于c# - 使用反射的工厂模式 - 使用与每个类关联的静态键进行类注册,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24553938/

相关文章:

c# - Excel图表+C#

c# - Type.GenericTypeArguments 属性与 Type.GetGenericArguments() 方法

php - 在 PHP 和 Laravel 中使用工厂模式

java - 具有扩展抽象类类型的工厂模式通用接口(interface)

ruby - 什么是 Ruby 工厂方法?

c# - 使用 Serializable() 从 XML 文件中填充一个数组

c# - 以无边界形式绘制夹具

c# - CodeDom 生成的代码中的额外括号

c# - 如何在编译时获得通用参数类型名称?

.net - 为什么 .Net 中没有 System.ClassNotFoundException?