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