До сих пор все, что вы говорите, звучит разумно для меня. Вы модулируете определенные области, определяете интерфейсы на разных уровнях абстракции и экспортируете каждый из ваших модулей с разными интерфейсами, т. Е. Каждый модуль будет зарегистрирован как несколько интерфейсов, которые он реализует. Вы сможете разрешать свои модули в соответствии с уровнем требуемой абстракции, получать все услуги, все бизнес-направления и т. Д. Итак, по-моему, вы направляетесь в правильном направлении.
Как бороться с метаданными? MEF обеспечивает экспорт метаданных, что, по-видимому, разумно использовать. Возможно, я не понял это полностью, но у меня был очень плохой опыт экспорта метаданных MEF. Насколько я помню, MEF хранит метаданные в виде пар ключ-значение, где ключ является строкой.
Даже если вы используете типизированные функции экспорта и использования метаданных, метаданные на самом деле не являются типичными. Скажем, у вас есть интерфейс «IMetadata» с свойством «PropertyA», и вы регистрируете тип (позволяет называть его Foo
ради творчества), который украшен соответствующим атрибутом в a, что MEF вызывает typesafe, способ (метаданные, реализующие IMetadata). Теперь предположим, что у вас есть второй интерфейс метаданных «IMetadataB», который также имеет свойство, называемое PropertyA
. Если вы теперь запросите разрешение Foo
с метаданными IMetadataB
, вы получите экземпляр, который вы зарегистрировали в первую очередь, потому что MEF удовлетворяет PropertyA
, существующим в парах ключ-значение метаданных, и строит тип метаданных соответствующего прокси, который реализует IMetadataB
.
Короче говоря, может быть, я несправедлив к MEF, но я прекратил использовать MEF, встроенный в поддержку метаданных, и рекомендовал бы вам сделать то же самое.
Поскольку я имею дело с очень сложными и длинными метаданными, включая документацию классов, которые я хочу быть тесно связан с классами, которые я экспортирую, я разработал систему, которая действительно работает для меня, хотя это немного нетрадиционно:
В принципе, я определяю интерфейс и базовое слово для своих метаданных, скажем MetadataBase
со строковым свойством, называемым Description
.
public class MetadataBase : IMetadata
{
public string Description { get; set; }
}
Затем для каждого класса я хочу иметь метаданные, я вывести класс (FooMetadata
) из этого базового класса и определить его частично в XAML. Тогда, в XAML, я определить конкретный класс значение свойства, например:
<md:MetadataBase.Description>
The description of my class goes here
</md:MetadataBase.Description>
С пользовательского атрибута, я связать тип метаданных для моего фактического класса:
[Export(typeof(IFoo))]
[AssociatedMetadata(typeof(FooMetadata))]
public class Foo : IFoo
{
// Whatever
}
метод расширения для объектов позволяет считывать метаданные с помощью отражения:
public static IMetadata GetMetadata(this object objectWithMetadata)
{
// Read attribute type
// Create instance of the metadata type, i.e. FooMetadata
// A caching mechanism can be implemented, if needed, but, honestly,
// my really big metadata objects including images and stuff like this
// are created within 3-5 ms
// Return this instance
}
Теперь вы в основном там, вы можете прочитать метаданные любого объекта, который имеет метаданные, как это:
var myObjectsMetadata = myObject.GetMetadata();
Вы можете использовать эти метаданные в MEF, когда вы делаете ваш AssociatedMetadataAttribute
реализовать интерфейс и зарегистрировать свои типы с помощью метаданных этого интерфейса. Ничто не будет замешано, потому что у вас есть один тип метаданных для всего, что содержит одно свойство, и ничего больше (тип).
Это решение не подходит для всего, но мне оно нравится, и ваш вопрос - хороший повод представить его. Надеюсь, поможет!
Помог ли мой ответ? – Marc