Структурная карта addalltypesof, созданная конкретным конструктором - PullRequest
0 голосов
/ 12 апреля 2011

Мне очень нравится StructureMap в качестве IOC-фреймворка, особенно при регистрации на основе соглашений.Теперь я пытаюсь сделать следующее: я хочу добавить все типы, которые реализуют определенный интерфейс, когда у класса есть конструктор по умолчанию (без параметров).И типы должны быть созданы с помощью этого конструктора.

Это то, что я до сих пор имею, который регистрирует правильные типы, но как мне указать, что конструктор по умолчанию должен использоваться при создании экземпляра.

public class MyRegistry : Registry    
{
    public MyRegistry()
    {
        Scan(
           x =>
           {
               x.AssemblyContainingType<IUseCase>();
               x.Exclude(t => !HasDefaultConstructor(t));
               x.AddAllTypesOf<IUseCase>();
           });
    }
    private static bool HasDefaultConstructor(Type type)
    {
        var _constructors = type.GetConstructors();
        return _constructors.Any(c => IsDefaultConstructor(c));
    }

    private static bool IsDefaultConstructor(ConstructorInfo constructor)
    {
        return !constructor.GetParameters().Any();
    }
}

1 Ответ

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

Есть несколько способов заставить StructureMap использовать определенный конструктор.Самое простое - поместить атрибут DefaultConstructor в конструктор, который вы хотите использовать.Предполагая, что вы не хотите этого делать, вам нужно будет создать пользовательское RegistrationConvention.

public class UseCaseRegistrationConvention : IRegistrationConvention
{
    public void Process(Type type, Registry registry)
    {
        if (type.IsAbstract || type.IsInterface || type.IsEnum)
            return;

        var useCaseInterface = type.GetInterface("IUseCase");
        if (useCaseInterface == null) 
            return;

        var constructor = type.GetConstructors().FirstOrDefault(c => !c.GetParameters().Any());
        if (constructor != null)
        {
            registry.For(useCaseInterface).Add(c => constructor.Invoke(new object[0]));
        }
    }
}

Затем использовать его при сканировании:

Scan(x =>
   {
       x.AssemblyContainingType<IUseCase>();
       x.With(new UseCaseRegistrationConvention());
   });
...