在初始化时自动将类类型添加到工厂类

本文关键字:类型 添加 工厂 初始化 | 更新日期: 2023-09-27 18:30:47

我面临的问题:我有一个工厂类,它有一个"Writer"列表,"Writer"是一个抽象类(目前)。我创建了多个实现"编写器"类的类。有没有办法自动将派生类添加到工厂类的列表中?每个类型中的一个,或作为类型。最好不必将代码写入派生类(例如必须实现方法),最好不必调用方法(特别是对于每个单独的派生类)。

演示/示例:

interface IWriter {
    void Write(string text);
}
class BlockWriter : IWriter {
    //something like this maybe, only this only calls on use of the class so it doesn't work...
    //static BlockWriter() {
    //    Factory.Add(new BlockWriter());
    //}
    public void Write(string text) {
        Console.WriteLine("Block: "  + text);
    }
}
class Factory {
    private static List<IWriter> writers = new List<IWriter>();
    public static List<IWriter> GetWriters() { return writers; }
    // I don't want to have to write every single one down like this.
    // I want a way to do this automatically, like withing the derived classes.
    public static void Build() {
        writers.Add(new BlockWriter());
        writers.Add(new ColumnWriter());
        writers.Add(new LineWriter());
        writers.Add(new SpiralWriter());
        writers.Add(new WaveWriter());
    }
    static Factory() {
        Build();
    }
    public static IWriter ChooseWriter(string input) {
        foreach (IWriter w in writers)
            if (w.GetType().Name.Equals(input))
                return w;
        return null;
    }
}

在初始化时自动将类类型添加到工厂类

这是

(奇怪的是)MEF(托管扩展性框架)[ImportMany]的主要目的。有关 MSDN 的文档。

要使用它,您首先需要标记 IWriter 接口的每个实现者

[Export(typeof(IWriter))]

这标志着它是 MEF 收集的类型(并且很容易忘记)。然后,您需要用[ImportMany]标记您的收藏(writers):

[ImportMany]
private static List<IWriter> writers;

最后,您需要为程序集设置一个组合容器,并调用 ComposeParts 。MEF 将获取它找到的与标记为 [ImportMany] 的列表的泛型参数类型匹配的所有导出,并使用每个匹配导出类型的单个实例填充列表。

//An aggregate catalog that combines multiple catalogs
AggregateCatalog catalog = new AggregateCatalog();
//Adds all the parts found in the same assembly as the Factory class
catalog.Catalogs.Add(new AssemblyCatalog(typeof(Factory).Assembly));
//Create the CompositionContainer with the parts in the catalog
CompositionContainer container = new CompositionContainer(catalog);
//Fill the lists
_container.ComposeParts(this);

大部分代码来自链接的 MSDN 页面。

我做了更多的研究,并使用工厂模式中的反射找到了更简单的答案。

public static IWriter ChooseWriter(string writer)
{
    Assembly currentAssembly = Assembly.GetExecutingAssembly();
    var currentType = currentAssembly.GetTypes().SingleOrDefault(t => t.Name == writer);
    return (IWriter )Activator.CreateInstance(currentType);
}

http://techtaunt.wordpress.com/2011/06/15/factory-pattern-with-reflection-c/或http://www.codeproject.com/Articles/37547/Exploring-Factory-Pattern(上次实现(第 4 次))

我认为您所说的是插件架构。

这可以通过像Autofac或MEF(严格来说不是Ioc容器)这样的Ioc容器很容易实现。

在这种情况下,我更喜欢 MEF,因为它对类型发现有更好的支持。