2013-08-21 2 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

Интерфейсы метаданных не должны иметь никаких свойств со установщиками. Вы должны изменить интерфейс IPlugInMetadata поэтому его свойства не будут иметь каких-либо сеттеры, иначе композиция будет терпеть неудачу:

interface IPlugInMetadata 
{ 
    string Name { get; } 
} 

Кроме того, вы должны рассмотреть возможность сделать свой PlugInMetadataAttribute класс наследует от ExportAttribute, а не Attribute. Это позволит использовать этот атрибут в качестве атрибута экспорта, и вам не придется использовать RegistrationBuilder.


EDIT: Я думаю, что я нашел вашу проблему

При попытке использовать 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

Совершенно --- По-видимому, я не могу присудить награду до завтра. –

Смежные вопросы