2016-01-15 3 views
1

у меня есть 2 классов для работы с данными:Виндзорский замок Комплекс регистрации для открываемых родовых типов

public class SqlDataProvider<T> : IDataProvider<T> where T : IEntity 
public class MongoDataProvider<T> : IDataProvider<T> where T : IEntity 

и у меня есть много моделей, как эти:

public class Account : ISqlDbEntity 
public class Log : IMongoDbEntity 

с этими интерфейсами:

public interface IMongoDbEntity : IEntity 
public interface ISqlDbEntity : IEntity 

Как зарегистрировать или можно зарегистрировать контейнер Windsor как generics, но MondoDbEntity будет использоваться с MongoDbProvider, а также модели MsSQl с SqlDataProvider.

container.Register(Component.For(typeof(IDataProvider<>)) 
     .ImplementedBy(typeof(SqlDataProvider<>)) 
     .LifestylePerWebRequest()); //I want this work only with ISqlEntity 

    container.Register(Component.For(typeof(IDataProvider<>)) 
     .ImplementedBy(typeof(MongoDataProvider<>)) 
     .LifestylePerWebRequest()); //I want this work only with IMongoDbEntity 

Я попытался это, но не работает:

container.Register(Component.For(typeof(IDataProvider<ISqlDbEntity>)) 
       .ImplementedBy(typeof(SqlDataProvider<>)) 
       .LifestylePerWebRequest()); 

      container.Register(Component.For(typeof(IDataProvider<IMongoDbEntity>)) 
       .ImplementedBy(typeof(MongoDataProvider<>)) 
       .DependsOn(Dependency.OnAppSettingsValue("databaseName", "MongoDatabaseName")) 
       .LifestylePerWebRequest()); 

Thx заранее!

+0

Я может быть что-то отсутствует, но почему не могу вам это сделать 'container.Register (Component.For (TypeOf (IDataProvider )) .ImplementedBy (TypeOf (SqlDataProvider )) .LifestylePerWebRequest ()); ' – pquest

+0

Thx, но это все еще не работает. Контейнер Windsor заставляет регистрировать каждый компонент один за другим, с таким типом регистрации. –

ответ

0

Этот заводский метод работает идеально!

 container.Register(Component.For(typeof(IDataProvider<>)) 
      .Forward(typeof(IReadOnlyDataProvider<>)) 
      .UsingFactoryMethod((kernel, model, creationContext) => 
      { 
       var type = creationContext.GenericArguments.First(); 
       if (type.GetInterface("ISqlDbEntity") != null) 
       { 
        var sqlProvider = typeof(SqlDataProvider<>); 
        return Activator.CreateInstance(sqlProvider.MakeGenericType(type), kernel.Resolve<DbContext>()); 
       } 

       var mongoProvider = typeof(MongoDataProvider<>); 
       return Activator.CreateInstance(mongoProvider.MakeGenericType(type), kernel.Resolve<MongoClientSettings>(), ConfigurationManager.AppSettings["MongoDatabaseName"]); 
      }) 
      .IsDefault() 
      .LifestylePerWebRequest()); 
1

Вы можете зарегистрироваться с несколькими интерфейсами, такими как:

container.Register(Component.For(typeof(IDataProvider<>),ISqlDbEntity)) 
     .ImplementedBy(typeof(SqlDataProvider<>)) 
     .LifestylePerWebRequest()); 


container.Register(Component.For(typeof(IDataProvider<>),IMongoDbEntity)) 
    .ImplementedBy(typeof(MongoDataProvider<>)) 
    .LifestylePerWebRequest()); 
+0

Благодарим вас за ответ. К сожалению, этот синтаксис не установлен, но я думал, что вы хотели бы написать это: container.Register (Component.For (typeof (IDataProvider <>)), typeof (ISqlDbEntity)) Но, к сожалению, это не работает. Виндзорский контейнер. Любая идея? –

2

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

container.Register(Component.For(typeof(IDataProvider<ISqlDbEntity>)) 
    .ImplementedBy(typeof(SqlDataProvider<>)) 
    .LifestylePerWebRequest()); 
+0

Спасибо за ваш ответ, я пробовал i (я зарегистрировал оба), но, к сожалению, это не работает, каждый DataProvider будет первой регистрацией, SqldataProvider. У вас есть идея? –

1

Как вы уже зарегистрировали оба экземпляра.

container.Register(Component.For(typeof(IDataProvider<ISqlDbEntity>)) 
       .ImplementedBy(typeof(SqlDataProvider<>)) 
       .LifestylePerWebRequest()); 

      container.Register(Component.For(typeof(IDataProvider<IMongoDbEntity>)) 
       .ImplementedBy(typeof(MongoDataProvider<>)) 
       .DependsOn(Dependency.OnAppSettingsValue("databaseName", "MongoDatabaseName")) 
       .LifestylePerWebRequest()); 

Затем в конкретных классах, которые используют этот интерфейс, вы можете указать, какую реализацию вы хотите использовать.

https://github.com/castleproject/Windsor/blob/master/docs/inline-dependencies.md Согласно документации:

container.Register(
    Component.For<ITransactionProcessingEngine>().ImplementedBy<TransactionProcessingEngine>() 
     .DependsOn(Dependency.OnComponent<ILogger, SecureLogger>()) 
); 

Или вы можете назвать свои реализации и использовать этот синтаксис.

container.Register(
    Component.For<ITransactionProcessingEngine>().ImplementedBy<TransactionProcessingEngine>() 
     .DependsOn(Dependency.OnComponent(typeof(ILogger), "secureLogger")) 
); 
+0

То есть что я хочу избежать, чтобы регистрировать каждый компонент по одному. Есть ли другое решение? :) –

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