我有一个软件,其中有一个负责打开文件的中央抽象Factory方法。起初,工厂知道它可以打开的所有文件类型以及它创建的相应对象(每个文件类型都有不同的处理程序),但随着时间的推移,它变得不切实际:首先,不适合摆弄工厂处理新文件类型时的类;其次,一些具体的文件处理程序存在于单独的DLL中,使它们无法从工厂访问! (文件处理程序有时需要工厂处理只索引到其他文件的路径的文件,因此他们必须知道工厂;如果工厂知道它们,则依赖关系将是循环的)
我们提出的解决方案是针对每个新对象类型注册'它本身与工厂一起,因此一旦创建了工厂方法,它将测试已注册的对象类型,以查看哪一个是最合适的并创建它。
最大的问题是:这些物体什么时候注册到工厂?理想情况下,它会在任何工厂调用之前发生一次。但是,因为在C#中你不能指望在访问类型之前调用静态c,我不知道如何做到这一点。我们当前的解决方案是执行一个dll范围的Initialize方法,该方法在工厂中注册对象类型,但这显然是我不喜欢的黑客攻击。
我们是否缺少一些设计模式?处理这个的另一种方法?需要注意的是,需要注册到工厂的文件处理程序位于单独的DLL中,必须引用工厂。
答案 0 :(得分:1)
我不会考虑使用dll扩展函数将dll初始化为hack。这正是DllMain对本机DLL的作用。
在每个dll中创建一个函数,在加载时初始化它并让它在工厂注册。然后将该函数调用为主应用程序中DLL加载代码的第一个函数。
然而,更好的方法是使用某种形式的依赖注入库,例如Unity,它可以通过configuration files或{自动处理DLL中的类型到工厂的注册{3}}
答案 1 :(得分:1)
您的应用程序设计似乎存在一些问题。 有一些技术可以像你那样制造循环依赖。通常程序员使用反转控制。 在这种情况下,您可以在处理器的“工厂”类接口中使用而不是具体实现。接口应该在工厂或另一个“核心”dll的同一个dll中定义,这将从你的dll引用。
答案 2 :(得分:1)
我们尝试从执行位置的所有程序集中加载所有类型,扫描它们以获取标记有特殊属性的静态方法并调用这些方法 - Scott Chamberlain提到的反射选项。
答案 3 :(得分:0)
我提出的最佳解决方案(与Scott Chamberlain讨论时)是要么使用Unity,要么使用属性来标记所有文件类型的处理程序,然后将它们全部加载到工厂的静态c'tor上通过反思。例如:
[FileHandler]
public class TxtFileHandler : FileHandlerBase
{
...
}
然后使用反射加载标记有FileHandler的所有类,并注册它们,例如使用属性将它们映射到文件扩展名。