C#make class自动注册

我有许多类型,我需要提供与外部世界对话的自定义函数。 例如,我可能有一个Widget和一个Sprocket,当我无法控制的世界数据到达并说“make a Widget”时,我需要调用一个Widget.Create()函数。 如果世界说“制造锤子”,那么我需要返回“锤子不存在”的错误。 但是,world-representation和type-name之间的映射不是1:1,所以我不能简单地使用reflection直接找到类型名称 – 我需要一个表。 (实际上,“名称”可以是例如特定的整数值。)

我理解如何使用从世界表示到类名映射的预定义表(或词典)。 我还了解如何在运行时扩展/更改此表,如果可能的类集更改。 (由于规则更改,或动态加载应用程序的部分,或其他。)

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

我以为我可以在每个类中使用一个静态成员,它在全局表中注册自己:

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

不幸的是,在执行/访问类中的某个函数之前,不会初始化静态字段,因此这不会在启动时运行。 (静态构造函数具有类似的限制,加上运行时的更多开销!)

接下来的想法是使用自定义属性来装饰类,该属性表示“在表中注册此类”。

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

不幸的是,“Register”属性不知道它附加到哪个类 – 只有MyClass类知道它具有Register属性。 (这对我来说是令人生气的,因为如果属性知道他们所附着的地方会很容易,很多很多情况下都是如此。但这是暂时的!)

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

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

我已经检查了其他资源(对CLR和IL的内部非常了解),这似乎是CLR和C#语言中的一个漏洞。 根本没有直接的方法可以在assembly负载或应用程序域准备时自动发生。 走类型并找到我感兴趣的类型是主要的坏方法。 事实上,在某些代码要求之前,并不总是创建属性,所以我不能使用带有类型参数的属性构造函数来自动注册!

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