简体   繁体   English

静态初始化BEFORE main

[英]Static initialization BEFORE main

I have a piece of software where there is a central abstract Factory method responsible for opening files. 我有一个软件,其中有一个负责打开文件的中央抽象Factory方法。 At first, the factory knew about all the file-types it can open and the corresponding objects it creates (every file-type has a different handler), but as time grew it became impractical: firstly, it was undesirable to fiddle with the factory class when handling new file-types; 起初,工厂知道它可以打开的所有文件类型以及它创建的相应对象(每个文件类型都有不同的处理程序),但随着时间的推移,它变得不切实际:首先,不适合摆弄工厂处理新文件类型时的类; secondly, some of the concrete file handlers existed in separate DLLs, making them inaccessible from the factory! 其次,一些具体的文件处理程序存在于单独的DLL中,使它们无法从工厂访问! (The file handlers sometimes require the factory to handle files who only index paths to other files, therefore they must know the factory; if the factory knew them, the dependency would be cyclic) (文件处理程序有时需要工厂处理只索引到其他文件的路径的文件,因此他们必须知道工厂;如果工厂知道它们,那么依赖关系将是循环的)

The solution we came up with is for every new object type to 'register' itself with the factory, so that once the factory method is created, it will test the registered object types to see which one is the most suitable one and create it. 我们提出的解决方案是为每个新的对象类型向工厂“注册”自己,这样一旦创建了工厂方法,它将测试注册的对象类型以查看哪一个是最合适的并创建它。

The largest problem is: when do these objects register themselves to the factory? 最大的问题是:这些物体什么时候注册到工厂? Ideally, it would happen once before any call to the factory. 理想情况下,它会在任何工厂调用之前发生一次。 However, since in C# you can't count on static c'tors to be called before accessing the type, I don't know how this can be done. 但是,因为在C#中你不能指望在访问类型之前调用静态c'tors,我不知道如何做到这一点。 Our current solution is to perform a dll-wide Initialize method which registers the object types with the factory, but this is obviously a hack which I dislike. 我们当前的解决方案是执行一个dll范围的Initialize方法,它将对象类型注册到工厂,但这显然是我不喜欢的hack。

Is there some design pattern we're missing? 我们缺少一些设计模式吗? A different way to handle this? 处理这个的另一种方法? It is important to note that the file handlers which need to register to the factory are in separate DLLs which MUST reference the factory. 需要注意的是,需要注册到工厂的文件处理程序位于必须引用工厂的单独DLL中。

I would not consider a dll wide function to initialize a dll to be a hack at all. 我不会考虑一个dll广泛的函数来初始化一个dll完全是一个黑客。 That is exactly what DllMain does for native DLL's. 这正是DllMain为本机DLL所做的事情。

Create a function in each dll that initializes it on load and have it register with the factory. 在每个dll中创建一个函数,在加载时初始化它并让它在工厂注册。 Then call that function as the first function of your DLL loading code in your main app. 然后将该函数调用为主应用程序中DLL加载代码的第一个函数。


However a even better way to do it is use some form of Dependency Injection library, for example Unity , that can handle the registration of types in DLLs to factories for you automatically via configuration files or via reflection . 然而,更好的方法是使用某种形式的依赖注入库,例如Unity ,它可以通过配置文件反射自动处理DLL中的类型到工厂的注册。

It seems that you have some problems with design of your application. 您的应用程序设计似乎存在一些问题。 There is some techniques to brake cyclic dependencies like yours. 有一些技术可以像你那样制造循环依赖。 Usually programmers use inversion of control for this. 通常程序员使用反转控制。 In this case you can use in your "factory" class interface of handler instead of concrete realization. 在这种情况下,您可以在处理器的“工厂”类接口中使用而不是具体实现。 Interface should be defined in same dll with factory or in another "core" dll, that will be referenced from both your dlls. 接口应该在工厂或另一个“核心”dll的同一个dll中定义,这将从你的dll引用。

我们尝试从执行位置的所有程序集中加载所有类型,扫描它们以获取标记有特殊属性的静态方法并调用这些方法 - Scott Chamberlain提到的反射选项。

The best solution I've come up with (when discussing it with Scott Chamberlain) is to either use Unity, or use attributes to tag all the file-type handlers, and then load them all on the factory's static c'tor via reflection. 我提出的最佳解决方案(与Scott Chamberlain讨论时)是使用Unity,或使用属性标记所有文件类型处理程序,然后通过反射将它们全部加载到工厂的静态c'tor上。 So for example: 例如:

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

And then load all the classes marked with FileHandler using reflection, and registering them, for example by using a property to map them to a file extension. 然后使用反射加载标记有FileHandler的所有类,并注册它们,例如通过使用属性将它们映射到文件扩展名。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM