ImportMany с метаданными, не импортирующими

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

Я пытаюсь использовать [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 ответа

Решение

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

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; }
}

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

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

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

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

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", true)] открытый класс 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;
    }
     */
}

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

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

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

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

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
{
}
Другие вопросы по тегам