ImportMany с метаданными, не импортирующими - PullRequest
5 голосов
/ 02 сентября 2010

Я пытаюсь понять это уже несколько дней, но безуспешно.

Я пытаюсь использовать [ImportMany] для импорта из каталога, полного DLL с экспортом типа IEditorSystem, которые имеют пользовательские метаданные типа IEditorSystemMetadata.Я хотел бы сначала получить метаданные и отправить их в некоторые текстовые поля и т. Д., Чтобы пользователь мог выбрать, какую систему EditorSystem использовать, и при выборе загрузить эту систему ...

Я следовал примерамНасколько я могу, вот что у меня есть.

[ImportMany]
public ObservableCollection<Lazy<IEditorSystem, IEditorSystemMetadata>> EditorSystemList

Это то, что он должен импортировать:

[Export(typeof(IEditorSystem))]
    [SignalSystemData("Very Very Long Name", "Short Name")]
    public class MyEditorSystem: IEditorSystem
    {
        public MyEditorSystem()
        {
        }
    }

и запуск:

AggregateCatalog Catalog = new AggregateCatalog(
                new DirectoryCatalog(@".\EditorSystems"),
                new AssemblyCatalog(Assembly.GetExecutingAssembly()));
            CompositionContainer Container = new CompositionContainer(Catalog);
            Container.ComposeParts(this);

Я могу видеть в Catalog.Parts и MyEditorSystem и viewmodel, у которого есть ImportMany, но EditorSystemList никогда не заполняется.Я не получаю ошибок композиции.

Я подумал, что это может быть как-то связано с Lazy <>, поэтому я попытался

public ObservableCollection<IEditorSystem> EditorSystemList

Не повезло.

ЕдинственноеЯ могу подумать, что я использую Cinch, который использует MEFedMVVM, который также использует MEF.Я не думаю это мешает, но я не совсем уверен.

Я полагаю, что я делаю это неправильно, кто-нибудь может понять это?

Обновление:

Реализация нового IComposer с именно тем каталогом, который вам нужен.

ImportMany все еще не работает, но только когда я пытаюсь импортировать метаданные вместе с ним.Метаданные - это всего лишь пара строк, и, насколько я могу определить, следует примерам.

НАКОНЕЦ нашел причину: реализации IEditorSystem находятся в отдельной DLL, как отмечалось ранее.Однако любые новые сборки dll не копируются в выходной подкаталог основного проекта.Я скопировал первый вручную и забыл добавить копию пост-сборки в проект dll.О, хорошо, узнал много вещей о MEF, так что не совсем потраченные впустую дни :)

Ответы [ 3 ]

1 голос
/ 15 апреля 2011

Возможно, мое решение решает и вашу проблему.

Я много работал, пытаясь обнаружить проблему.

, тогда я получил следующее решение:

Интерфейс метаданных должен содержатьтолько одно свойство того же типа:

int, bool, string и т. д. Если вы, например, поместите два свойства Int, ImportMany> не будет работать и всегда будет возвращать 0.

для каждого свойства интерфейса вы должны поместить атрибут ExportMetadata в экспортируемый класс в.

, например,

открытый интерфейс IMyExportMetadata {int a {get;} строка b {get;} bool c {get;}}

[Export (typeof (IMyInterface)) [ExportMetadata ("a", 0)] [ExportMetadata ("b", "string")] [ExportMetadata ("c", правда)] открытый класс myExportedClass: IMyInterface {}

для работы с несколькими логическими значениями, например, необходимо создать пользовательский атрибут экспорта, реализующий интерфейс метаданных, подобный следующему:

[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public class ExportUserPartAttribute : ExportAttribute, IUserPartMetadata
{
    #region Implementation of IUserPartMetadata

    public int TipoPart { get; set; }
    public string Regiao { get; set; }
    public bool IsLogin { get; set; }
    public bool IsMenu { get; set; }
    public bool IsHome { get; set; }
    public bool IsListagem { get; set; }
    public bool IsFormulario { get; set; }

    #endregion

    public ExportUserPartAttribute()
        : base(typeof(IUserPart))
    {

    }

    /*
    public ExportUserPartAttribute(int tipoPart, string regiao)
        : base(typeof(IUserPart))
    {
        this.TipoPart = tipoPart;
        this.Regiao = regiao;
    }
     */
}
1 голос
/ 03 сентября 2010

Не видя ваш код, я думаю, все, что вам нужно изменить, это

public ObservableCollection<Lazy<IEditorSystem, IEditorSystemMetadata>> EditorSystemList  

должно быть

public IEnumerable<Lazy<IEditorSystem, IEditorSystemMetadata>> EditorSystemList;

Вот пример:

class Program
{
    static void Main(string[] args)
    {
        var c = new Class1();
        var v = c.EditorSystemList;
        foreach (var lazy in v)
        {
            if (lazy.Metadata.LongName == "Very Very Long Name")
            {
                var v2 = lazy.Value;
                // v2 is the instance of MyEditorSystem
            }
        }
    }
}

public class Class1
{
    [ImportMany]
    public IEnumerable<Lazy<IEditorSystem, IEditorSystemMetadata>> EditorSystemList;

    public Class1()
    {
        var catalog = new AggregateCatalog(
            new AssemblyCatalog(Assembly.GetExecutingAssembly()));
        var container = new CompositionContainer(catalog);
        container.ComposeParts(this);
    }
}

[Export(typeof(IEditorSystem))]
[SignalSystemData("Very Very Long Name", "Short Name")]
public class MyEditorSystem : IEditorSystem { }

public interface IEditorSystem { }

[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class SignalSystemDataAttribute : ExportAttribute
{
    public SignalSystemDataAttribute(string longName, string shortName)
        : base(typeof(IEditorSystem))
    {
        LongName = longName;
        ShortName = shortName;
    }
    public string LongName { get; set; }
    public string ShortName { get; set; }
}

public interface IEditorSystemMetadata
{
    string LongName { get; }
    string ShortName { get; }
}
0 голосов
/ 15 апреля 2011

Возможно, мое решение тоже решит вашу проблему.

Я много работал, пытаясь обнаружить проблему.

тогда я получил следующее решение:

Интерфейс метаданных должен содержать только одно свойство того же типа:

int, bool, string и т. Д. Если вы, например, задаете два свойства int, ImportMany<Lazy<t,m>> не будет работать и всегда будет возвращать 0.

для каждого свойства интерфейса вы должны поместить атрибут ExportMetadata в экспортируемом классе в.

например,

public interface IMyExportMetadata
{
  int a {get;}
  string b {get;}
  bool c {get;}
}

[Export(typeof(IMyInterface))
[ExportMetadata("a", 0)]
[ExportMetadata("b", "string")]
[ExportMetadata("c", true)]
public class myExportedClass: IMyInterface
{
}
...