2013-08-21 28 views
0

我试图进口零部件,包括自定义MetadataAttribute,继势在必行模型,使用.NET 4.5无法导入部分与元数据

下面,我已经包括了最简单的例子,我可以,这说明问题。

执行此代码时,将调用Engine类构造函数,并传递一个空的Enumerator,而不是两个插件,这两个插件显然是项目的一部分。

目前我怀疑PluginMetadata属性,但我没有看到如何在没有它的情况下将元数据放入目录。

using System; 
using System.Collections.Generic; 
using System.ComponentModel.Composition; 
using System.ComponentModel.Composition.Hosting; 
using System.ComponentModel.Composition.Registration; 
using System.Reflection; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var builder = new RegistrationBuilder(); 
      builder.ForTypesDerivedFrom<IPlugIn>().Export<Lazy<IPlugIn, IPlugInMetadata>>(); 
      builder.ForType<Engine>().Export(); 
      var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly(), builder); 
      var container = new CompositionContainer(catalog); 

      var engine = container.GetExport<Engine>(); 
      engine.Value.Run(); 

     } 
    } 

    internal class Engine 
    { 
     private IEnumerable<Lazy<IPlugIn, IPlugInMetadata>> PlugIns { get; set; } 
     public Engine(IEnumerable<Lazy<IPlugIn, IPlugInMetadata>> plugins) 
     { 
      PlugIns = plugins; 
     } 

     public void Run() 
     { 
      foreach (var plugIn in PlugIns) 
      { 
       Console.WriteLine("Starting {0}", plugIn.Metadata.Name); 
       plugIn.Value.Work(); 
      } 
     } 
    } 

    interface IPlugIn 
    { 
     void Work(); 
    } 

    interface IPlugInMetadata 
    { 
     string Name { get; } 
    } 

    [MetadataAttribute] 
    class PlugInMetadataAttribute : ExportAttribute, IPlugInMetadata 
    { 
     public PlugInMetadataAttribute(string name) 
     { 
      this.name = name; 
     } 

     private readonly string name; 
     public string Name { get { return name; } } 
    } 

    [PlugInMetadata("PlugIn1")] 
    class PlugIn1 : IPlugIn 
    { 
     public void Work() 
     { 
      Console.WriteLine("PlugIn 1 working"); 
     } 
    } 

    [PlugInMetadata("PlugIn2")] 
    class PlugIn2 : IPlugIn 
    { 
     public void Work() 
     { 
      Console.WriteLine("PlugIn 2 working"); 
     } 
    } 
} 

回答

1

元数据接口不能与setter具有任何属性。你应该修改IPlugInMetadata接口,因此它的性能不会有任何的制定者,否则构成将失败:

interface IPlugInMetadata 
{ 
    string Name { get; } 
} 

此外,你应该考虑从ExportAttribute而不是Attribute让你PlugInMetadataAttribute类继承。这将允许使用此属性作为导出属性,您不必使用RegistrationBuilder


编辑:我想我找到了你的问题

当试图在构造函数中使用ImportMany,你必须指定明确这样,所以你的构造应该是这样的:

[ImportingConstructor] 
public Engine([ImportMany] IEnumerable<Lazy<IPlugIn, IPlugInMetadata>> plugins) 
{ 
    PlugIns = plugins; 
} 

或者,您可以选择将其作为属性导入:

[ImportMany] 
private IEnumerable<Lazy<IPlugIn, IPlugInMetadata>> PlugIns { get; set; } 

作为一个侧面说明,从ExportAttribute派生时,你想包括自动导出一部分IPlugIn构造函数:

[MetadataAttribute] 
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)] 
class PlugInMetadataAttribute : ExportAttribute, IPlugInMetadata 
{ 
    public PlugInMetadataAttribute() 
     : base(typeof(IPlugIn)) 
    { 
    } 

    public PlugInMetadataAttribute(string contractName) 
     : base(contractName, typeof(IPlugIn)) 
    { 
    } 

    public string Name { get; set; } 
} 
+0

阿迪我已经试过你的建议,这当然有可能响起。我编辑了我原来的问题,并相应更新了代码。但是引擎仍然没有收到任何插件。必须有更多的难题。 –

+0

@RalphShillington查看我的编辑 –

+0

完美---显然我不能奖励赏金直到明天。 –