我正在编写一个程序,该程序利用Microsoft的Managed Extensibility Framework(MEF)在运行时加载第三方插件类。对于要导入的类,它必须扩展AbstractPlugin
并具有以下属性:
ExportAttribute(Type contractType)
,其中contractType
始终为typeof(AbstractPlugin)
,因此MEF可以找到该类别。PartCreationPolicyAttribute(CreationPolicy creationPolicy)
,其中creationPolicy
始终为CreationPolicy.Shared
,指示MEF为所有导入程序集共享一个类实例。PluginClassAttribute(string name)
,其中name
是插件的名称。所以一个插件的声明是这样的:
[Export(typeof(AbstractPlugin))]
[PartCreationPolicy(CreationPolicy.Shared)]
[PluginClass("Cool plugin")]
class CoolPlugin : AbstractPlugin { /* ... */ }
最后,在导入期间会检查插件,以确保它们具有正确的属性。
但是我对这种解决方案不满意。由于这些属性中的两个永远不会在其声明中发生变化,因此设计者不应自行声明它们。我希望不指定这些属性就可以编写插件。
[我的第一个想法是使PluginClassAttribute
扩展这些属性以封装其行为,但是不幸的是,这些属性是密封的,对象不可能从多个父对象继承。
然后我考虑将这些属性添加到AbstractPlugin
,但是从元数据中查看它们的声明后,我意识到它们的AttributeUsage
正在禁用继承。
我考虑过但没有探索的另一条路径是在运行时注入属性。如果可能的话,这意味着我必须在注入允许导入的属性之前导入这些类。是鸡肉还是鸡蛋。
我没有主意,但我仍然相信有一种封装这些属性的方法。有人可以给我提示吗?
[如果有人去掉了所有继承属性的可能方式,那么可能是因为他们希望您直接在导出的类型上单独指定所有这些属性。
[如果您热衷于删除这项繁琐的工作(我对此表示同情),我看到了一个显而易见的解决方案-您可以编写一些代码中的内容,并将属性添加到源代码中。如果可以访问T4 templates(Visual Studio工具的一部分),则可以参考here以解决非常相似的问题。如果您不这样做,那么简单如编写]
// !MEF_EXPORT
然后是一个脚本,该脚本将遍历您的源并将所有此类出现替换为适当的属性集。将其添加为编译前的操作,您几乎可以做到。解析类型名称以传递给
ExportAttribute
有点麻烦,但是肯定是可行的。