Reflection MEF:加载具有不同属性的部件(插件)

Reflection MEF:加载具有不同属性的部件(插件),reflection,plugins,c#-3.0,interface,mef,Reflection,Plugins,C# 3.0,Interface,Mef,简要背景: 我的团队已决定使用Microsoft的托管扩展性框架(MEF),以便为向系统中添加新的“提供者”提供一个可扩展的模型 这使我们能够相对轻松地插入新的第三方提供商 注意:MEF的使用和启动以及运行都非常简单,这给我留下了深刻的印象 我的问题: 由于这些提供程序通常具有不同的相关属性,因此在运行时将这些提供程序加载到系统中时,我们需要访问提供程序数据流和属性 由于不同的属性,应该采取什么方法来使用所述提供者插件?注意到他们都做相似的工作 我的解决方案: 创建提供商必须遵守的接口,从而在每

简要背景:

我的团队已决定使用Microsoft的托管扩展性框架(MEF),以便为向系统中添加新的“提供者”提供一个可扩展的模型

这使我们能够相对轻松地插入新的第三方提供商

注意:MEF的使用和启动以及运行都非常简单,这给我留下了深刻的印象

我的问题:

由于这些提供程序通常具有不同的相关属性,因此在运行时将这些提供程序加载到系统中时,我们需要访问提供程序数据流和属性

由于不同的属性,应该采取什么方法来使用所述提供者插件?注意到他们都做相似的工作

我的解决方案:

创建提供商必须遵守的接口,从而在每个第三方提供商周围创建“包装器”,从而形成一致的接口/ 用于与每个提供者协作的编程模型

插件=第三方数据源(提供程序)+通用接口实现

+ve: 对于所述插件,不需要更复杂的基于反射的动态“插件”

-ve: 必须为每个提供者编写一个包装器。(我们需要添加MEF导出标签)

进一步说明:

对我来说,接口/包装器方法是最简单的,但我被告知要研究一种基于反射的方法,这种方法可以利用反射,以便在运行时发现可以向系统公开的属性

我不赞成任何一种解决方案胜过另一种解决方案,但我有兴趣听取社区的想法(其中大多数比我更有经验)

谢谢。

你所说的“属性”和“数据流”不是很清楚,但仍然是

是的,公共接口总是一件好事。既然你有这些“属性”之类的东西,我建议如下:

interface IProperty
{
    string Name { get; }
    object Value { get; }
}

interface IDataStreamProvider
{
    Stream OpenStream();
}

interface IPlugin
{
    ReadOnlyCollection<IProperty> Properties { get; }

    ReadOnlyCollection<IDataStreamProvider> DataStreams { get; }
}
[Rule("AddOneRule", "Adds one to the value")]
public class AddOneRule {
}

考虑到可维护性问题,应该尽可能避免反射。

我为添加这样的信息所做的是为插件创建一些自定义属性,然后在加载插件时使用MEF读取这些属性。您可以向属性类中添加任何内容,如名称、枚举、整数和其他字符串,而且使用起来非常简单。但是要小心,新的preview6确实改变了一些处理方式

[MetadataAttribute]
public class MyMetadataAttribute : Attribute
{
    public MyType MyUsage { get; set; }
}

public interface IMyMetadataView
{
    MyType MyUsage { get; }
}

public enum MyType
{
    Undefined,
    TypeOne,
    TypeTwo
}
然后在插件中你可以这样定义它

[Export(typeof(IMyInterface))]
[MyMetadataAttribute(MyUsage = MyType.TypeOne)]
public class PluginClass: IMyInterface
{
}
您还需要将内容添加到导入中

[ImportMany(AllowRecomposition = true)]
public IEnumerable<Lazy<IMyInterface, IMyMetadataView>> plugins { get; set; }

同样,这也是使用7月份发布的preview 6的方法。

实际上,在preview 6中,我们已经打开了导出,并允许您创建包含元数据的自定义导出属性,从而消除了零件作者添加单独导出的需要。我们所有的导入属性也都是未密封的

[MetadataAttribute]
[AttributeUsage(AllowMultiple=false)] 
public class RuleAttribute : ExportAttribute {
  public RuleAttribute(string name, string description) {
    Name=name;
    Description=description;

  } : base(typeof(IRule))

  public string Name {get;private set;}
  public string Description {get; private set;}
}
上面的RuleAttribute导出IRule,还允许提供名称元数据

使用方法如下所示:

interface IProperty
{
    string Name { get; }
    object Value { get; }
}

interface IDataStreamProvider
{
    Stream OpenStream();
}

interface IPlugin
{
    ReadOnlyCollection<IProperty> Properties { get; }

    ReadOnlyCollection<IDataStreamProvider> DataStreams { get; }
}
[Rule("AddOneRule", "Adds one to the value")]
public class AddOneRule {
}

Glenn

除了少量添加之外,RuleAttribute类还应标记为:[AttributeUsage(AllowMultiple=false)]已更新,谢谢!我很喜欢StackOverflow的功能,它可以让你编辑;-)