2016-10-19 8 views
0

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

container.Register(typeof(IRepository<>), 
    () => new Repository<object>("connString"), 
    Lifestyle.Transient); 

Таким образом, в лямбда Я хотел бы создать экземпляр хранилища с конкретной общего типа вместо использования объекта.

ответ

3

Перегрузки Register, которые принимают в лямбда, не поддерживают дженерики. Причина этого в том, что Simple Injector больше не сможет анализировать граф объектов для вас и делать какие-либо анализы от вашего имени.

Есть несколько решений, но то, что это, вероятно, проще всего извлечь параметр строки соединения в объект данных, и пусть хранилище зависит от того:

public class ConnectionStringSettings 
{ 
    public readonly string ConnectionString; 

    public ConnectionStringSettings(string connectionString) { 
     this.ConnectionString = connectionString; 
    } 
} 

container.RegisterSingleton(new ConnectionStringSettings("constr")); 
container.Register(typeof(IRepository<>), typeof(Repository<>)); 

Другим вариантом является регистрация строки подключения непосредственно с помощью условной регистрации:

container.RegisterConditional(typeof(string), 
    Lifestyle.Singleton.CreateRegistration(typeof(string), 
     () => "constr", container), 
    c => c.Consumer.ImplementationType.Name == typeof(Repository<>).Name); 

Таким образом, вы можете оставить аргумент конструктора, как есть. Недостатком является то, что эта регистрация несколько сложнее, и эта условная регистрация работает только со ссылочными типами, такими как строки. Мы могли бы fix это в v4.

Другим вариантом является регистрация всех реализаций в явном виде:

container.Register<IRepository<User>>(() => new Repository<User>("connString")); 
container.Register<IRepository<Order>>(() => new Repository<Order>("connString")); 
container.Register<IRepository<Asset>>(() => new Repository<Asset>("connString")); 

Другой вариант заключается в использовании незарегистрированной разрешение типа:

container.ResolveUnregisteredType += (s, e) => 
{ 
    Type serviceType = e.UnregisteredServiceType; 

    if (serviceType.IsGenericType && 
     serviceType.GetGenericTypeDefinition() == typeof(IRepository<>)) 
    { 
     Type implementationType = typeof(Repository<>) 
      .MakeGenericType(serviceType.GetGenericArguments()[0]); 

     Registration r = Lifestyle.Transient.CreateRegistration(
      serviceType, 
      () => Activator.CreateInstance(implementationType, "connectionString"), 
      container); 

     e.Register(r); 
    } 
}; 

Еще один вариант для override Simple Injector's default behavior when it comes to parameter injection, но это требует довольно много кода, поэтому это не то, что я обычно советую.

 Смежные вопросы

  • Нет связанных вопросов^_^