main之前的静态初始化

本文关键字:静态 初始化 main | 更新日期: 2023-09-27 18:05:33

我有一个软件,其中有一个中央抽象工厂方法负责打开文件。起初,工厂知道它可以打开的所有文件类型和它创建的相应对象(每种文件类型都有不同的处理程序),但随着时间的推移,它变得不切实际:首先,在处理新的文件类型时,不希望摆弄工厂类;其次,一些具体的文件处理程序存在于单独的dll中,这使得它们从出厂时就无法访问!(文件处理程序有时要求工厂处理那些只索引其他文件路径的文件,因此它们必须知道工厂;如果工厂知道它们,那么依赖关系将是循环的)

我们提出的解决方案是每个新对象类型都要在工厂中"注册"自己,这样一旦工厂方法被创建,它就会测试注册的对象类型,看看哪一个是最合适的,然后创建它。

最大的问题是:这些对象什么时候把自己注册到工厂?理想情况下,它应该在任何呼叫工厂之前发生一次。然而,由于在c#中,你不能指望在访问类型之前调用静态C 'tors,我不知道如何做到这一点。我们目前的解决方案是执行一个dll范围内的Initialize方法,该方法向工厂注册对象类型,但这显然是我不喜欢的一个hack。

我们是否错过了一些设计模式?另一种处理方式?需要注意的是,需要注册到工厂的文件处理程序位于必须引用工厂的单独dll中。

main之前的静态初始化

看来你的应用程序设计有一些问题。有一些技巧可以阻止像你这样的循环依赖。通常程序员使用控制反转来实现这一点。在这种情况下,您可以在"工厂"类接口中使用处理程序,而不是具体实现。接口应该定义在相同的dll与工厂或在另一个"核心"dll,这将从你的dll引用。

我不认为一个dll范围的函数来初始化一个dll是一个hack。这正是DllMain为本地DLL所做的。

在每个dll中创建一个函数,在加载时初始化它,并将它注册到工厂。然后在主应用程序中调用该函数作为DLL加载代码的第一个函数。


然而,更好的方法是使用某种形式的依赖注入库,例如Unity,它可以通过配置文件或反射自动处理dll中的类型到工厂的注册。

我们从执行位置的所有程序集中加载所有类型,扫描它们以查找带有特殊属性的静态方法并调用这些方法——Scott Chamberlain提到的反射选项

我想到的最佳解决方案(当与Scott Chamberlain讨论时)是要么使用Unity,要么使用属性标记所有文件类型处理程序,然后通过反射将它们加载到工厂的静态c'tor上。例如:

[FileHandler]
public class TxtFileHandler : FileHandlerBase
{
...
}

然后使用反射加载所有标记为FileHandler的类,并注册它们,例如通过使用属性将它们映射到文件扩展名