2015-01-19 1 views
1

Я использую контейнер IoC SimpleInjector и пытаюсь подключиться к функциям при запуске приложения (контейнер сообщит, какие обработчики команд и обработчики запросов она зарегистрирована, и мы будем регистрировать команды и запросы, которые были зарегистрированы в качестве родовых типов):Проверка того, что регистрация IoC реализует интерфейсы команд или запросов и возвращает общий параметр

var suppportedCommands = new List<Type>(); 
var container = Bootstrapper.SimpleInjectorContainer; 

foreach (var registration in container.GetCurrentRegistrations()) 
{ 
    var type = registration.ServiceType; 

    var isCommandHandler = type.GetInterfaces().Any(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(ICommandHandler<>)); 

    if (isCommandHandler) 
    { 
     suppportedCommands.Add(type.GetGenericArguments().First()); 
    } 
} 

Хотя регистрации возвращаются правильно, я, кажется, не быть в состоянии:

  1. Проверьте, не является ли это типом lements ICommandHandler<SetUserStatusToVerifiedCommand>

  2. Если да, то получить общий аргумент, чтобы мы могли следить за команды мы поддерживаем

В качестве примера, когда я нарушу точку на возвращенную регистрации, которая имеет тип SetUserStatusToVerifiedCommandHandler, переменная isCommandHandler всегда ложно и строка типа показана как:

{Name = "ICommandHandler`1" FullName = "MyApp.ICommandHandler`1[[MyApp.Application.UserStatus.SetUserStatusToVerifiedCommand, MyApp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]"}` 

и мои интерфейсы и командные обработчики реализованы как:

public interface ICommand 
{ 
} 

class SetUserStatusToVerifiedCommand : ICommand 
{ 
    string UserId; 
    DateTime VerifiedOn; 
} 

class SetUserStatusToVerifiedCommandHandler : ICommandHandler<SetUserStatusToVerifiedCommand> 
{ 
    public void Handle(SetUserStatusToVerifiedCommand commandToHandle) 
    { 
    } 
} 

Любые идеи, что я делаю неправильно, пожалуйста?

В качестве побочного элемента, если есть какой-либо более простой способ достичь вышеуказанного с помощью SimpleInjector, вам будет оценено достоинство.

+0

я бы, вероятно, сделать это наоборот. Поскольку ваши команды отмечены «ICommand», получение всех команд должно быть таким же простым, как «AppDomain.CurrentDomain.GetAssemblies(). GetTypes(). Где (typeof (ICommand) .IsAssignableFrom). Где (t =>! T.IsAbstract) '. – Steven

+0

Благодаря @Steven существует потенциал того, что мы будем размещать разные обработчики команд в разных контейнерах, так как в одном и том же процессе могут быть две разные системы (ограниченные контексты) ... не продумали идею полностью реализовать последствия с пометкой, но, по крайней мере, первоначально контейнер был бы четкой границей, так как у меня будет один контейнер на «систему». – g18c

+0

В этом случае то, что вы делаете, имеет смысл. – Steven

ответ

1

Проблема заключается в этом утверждении:

var type = registration.ServiceType; 
var isCommandHandler = type.GetInterfaces().Any(x => x.IsGenericType 
    && x.GetGenericTypeDefinition() == typeof(ICommandHandler<>)); 

Метод Type.GetInterfaces() возвращает список всех интерфейсов, что определенный тип орудий. Но registration.ServiceType будет закрытой родовой версией ICommandHandler<T>. Поэтому вы в основном спрашиваете, какие интерфейсы реализуют. И GetInterfaces() не вернет сам интерфейс, если вызван на этом интерфейсе.

Так вместо этого, вам нужно сделать, это:

var type = registration.ServiceType; 

var isCommandHandler = type.IsGenericType && 
    type.GetGenericTypeDefinition() == typeof(ICommandHandler<>));