Как я могу сканировать и регистрировать классы с атрибутами, используя StructureMap? - PullRequest
3 голосов
/ 20 июня 2011

Например, я хочу зарегистрировать все классы с атрибутом Service , используя StructureMap

[Service]
public class A {}

Ответы [ 2 ]

3 голосов
/ 20 июня 2011

Насколько я знаю, вам необходимо создать пользовательский IRegistrationConvention, найденный в пространстве имен StructureMap.Graph.

Реализация соглашения

public class ServiceDiscoveryConvention
                                : StructureMap.Graph.IRegistrationConvention
{
    public void Process(Type type, Registry registry)
    {
        // check if type has attribute
        // add to registry using the registry variable
    }
}

Добавить соглашение к сканеру

Scan(cfg =>
       {
            cfg.TheCallingAssembly(); // or whatever assemblies you are scanning
            cfg.Convention<ServiceAttributeConvention>();
        });

Замечания

Если вы свободны в своем решении, вы можете использовать интерфейсы вместо атрибутов,Используя интерфейс, вы можете предоставить общий контракт для всех классов, и с ними гораздо проще работать, когда проект расширяется.

Атрибуты имеют тенденцию распространяться по всему коду, их рефакторинг может быть реальнымболь.Интерфейсы имеют гораздо лучшую инструментальную поддержку, когда дело доходит до рефакторинга.

Я использую интерфейсы для аналогичной задачи (система плагинов), соглашение вроде

public class TypeScanner<T> : IRegistrationConvention
{
    private static readonly Type PluginInterface = typeof(T);

    public void Process(Type type, Registry registry)
    {
        if (type.IsAbstract || type.BaseType == null) return;
        if (PluginInterface.IsAssignableFrom(type) == false) return;

        registry.For(PluginInterface).Singleton().Add(instance);
    }
}

будет таким же:

Scan(cfg =>
       {
            cfg.TheCallingAssembly(); // or whatever assemblies you are scanning
            cfg.Convention<TypeScanner<IYourService>>();
        });

Если ваше соглашение принимает аргументы конструктора, вы можете использовать With:

Scan(cfg =>
       {
            cfg.TheCallingAssembly(); // or whatever assemblies you are scanning
            var convention = new SomeConvention(x,y,z);
            cfg.With(convention);
        });
2 голосов
/ 24 июня 2011

Нет необходимости регистрировать тип в StructureMap, если вы не собираетесь получать его через интерфейс.

Дано:

[Service]
public class A {}

[Service]
public class B {}

Следующий код будет работать нормально, а StructureMap будет заполнять любые зависимости конструктора в A или B без какой-либо специальной регистрации:

var instanceA = ObjectFactory.GetInstance<A>();
var instanceB = ObjectFactory.GetInstance<B>();
...