2015-08-09 83 views
3

我有一些类型,我需要提供与外部世界交谈的自定义函数。例如,我可能有一个Widget和一个Sprocket,并且当我不控制的世界中的数据到达并说“make a Widget”时,我需要调用Widget.Create()函数。 如果世界说“做一个锤子”,那么我需要返回一个“锤子不存在”的错误。 但是,world-representation和type-name之间的映射不是1:1,所以我不能直接使用反射来直接查找类型名称 - 我需要一个表。 (实际上,“名称”可能是一个特定的整数值。)C#make类自动注册

我明白我如何使用从世界表示到类名映射的预定义表(或字典)。 我也理解如何在运行时扩展/更改此表,如果可能的类的集合更改。 (因为规则的变化,或动态加载应用程序的部分,或其他)

然而,所有这些都需要重复 - 我必须都实现我的类,然后,在代码中的其他地方,请记得添加一个“这个类在外部世界中有这个名字”的实例。 这是一种代码味道,因为将来有时我会写一个新类(或删除一个旧类),忘记更新表,然后花时间调试它为什么不能正常工作。

我认为我可以在每个注册自身在全球表类使用静态成员:

public static Registration Me = new Registration(typeid(MyClass), "My Name"); 

不幸的是,静态字段不会被初始化,直到执行类中的一些功能/访问,所以这在启动时不运行。 (静态构造函数具有类似的限制,加上运行时的更多开销!)

接下来的想法是用一个自定义属性来修饰类,该属性说“在表中注册这个类”。

[Register("My Name")] 
class MyClass : .... { 
} 

不幸的是,“Register”属性不知道它连接了什么类 - 只有MyClass类知道它具有Register属性。 (这对我来说真是太令人气愤了,因为如果属性知道它们被连接的位置,在很多情况下它就会非常方便,但这是一个问题!)

所以,我能想到的最坏的实现是迭代所有程序集的所有类型,使用反射,并检查它们是否具有此属性,如果它们确实存在,则将它们注册到表中。这就是说,既不优雅也不高效。

有没有更好的方法来自动注册类,而无需使用中央注册表来更新其他源文件?

+1

为什么不是许多IoC框架之一(很多都有自动注册,虽然被称为“某些东西”)?还有更多像MEF这样的组件/发现框架。 – user2864740

+0

你没有告诉你如何,何地或什么时候“autoregister”你的类,但你可能会发现这个问题很有趣:http://stackoverflow.com/questions/7692781/most-efficient-way-to-get-all -types-in-appdomain-marked-with-a-specific-attribut – t3chb0t

+1

我想在程序启动时自动注册,并且如果我每次动态加载更多程序集,加载时(或之后)。 My当前的解决方案是遍历所有程序集,迭代所有类型,查找注释,注册。这比我想要的效率更低,更不优雅。 我不是在寻找一个外部框架,除非它只会自动发现,并且比上面建议的更有效。我正在寻找一种语言技术,可以使自动发现更加优雅高效。 –

回答

0

我检查了其他资源(对CLR和IL的内部知识非常了解),看起来这是CLR和C#语言中的一个漏洞。根本没有直接的方式来使装配加载或应用程序准备时自动发生。走路的类型,找到我感兴趣的类型是最糟糕的方式。实际上,在某些代码要求它们之前并不总是创建属性,所以我不能使用具有类型参数的属性构造函数来自动注册!

这当然不是很好,因为如果有八个不同的代码片段,每个代码片段都有他们自己想要做的注册,那么每个片段都必须遍历所有类型,然后进行检查他们自己的。解决这个问题的唯一方法就是放弃模块化,并在应用程序开始时将所有类型不同的“事物”集中到一个单一的全能型循环中。然而,第三方库(包括MEF)仍然不会进入这个循环,所以这里只有一个不可避免的开销块,或者是一个不可避免的重复 - 我的选择,作为开发人员。