2015-10-15 2 views
1

У меня есть простой структуры классов, интерфейсов следующим образом:конфигурации Unity с наследованием

public interface IMessagingClient (interface supporting service bus queue operation) 

public class ServiceBusMessagingClient : IMessagingClient  (real implementation) 

public class MockMessagingClient : IMessagingClient (mock implementation for our unit test) 

public class FailoverMessagingClient : IMessagingClient  (this implementation internally uses 2 clients and switches roles b/w 2 as and when disaster in a datacenter occur) 
{ 
private IMessagingClient PrimaryClient { get; set; } 
private IMessagingClient SecondaryClient { get; set; } 
} 

Мы загружаем единство конфигурации из web.config/app.config и использовать его в коде продукта и тестового кода.

Мы хотим, чтобы следующее:

  • Для сценария производства, PrimaryClient и SecondaryClient должны типа ServiceBusMessagingClient

  • Для тестирования сценария, PrimaryClient и SecondaryClient должны типа MockMessagingClient

Наш текущая конфигурация конфигурации выглядит так:

<container name="azure"> 
<register type="IMessagingClient" mapTo="FailoverMessagingClient"/> 
</container> 

Нужно ли использовать некоторые перехватчики для достижения этого? Или, определяя ctor в FailoverMessagingClient и используя ctor injection?

Некоторые предложения были бы замечательными!

ответ

2

Вы можете сделать это, используя именованные регистрации.

Например, учитывая следующий пример настройки:

namespace ConsoleApplication8 
{ 
    using Microsoft.Practices.Unity; 
    using Microsoft.Practices.Unity.Configuration; 

    public interface IMessagingClient { } 

    public class ServiceBusMessagingClient : IMessagingClient { } 

    public class MockMessagingClient : IMessagingClient { } 

    public class FailoverMessagingClient : IMessagingClient 
    { 
     private readonly IMessagingClient primaryClient; 
     private readonly IMessagingClient secondaryClient; 

     public FailoverMessagingClient(IMessagingClient primaryClient, IMessagingClient secondaryClient) 
     { 
      this.primaryClient = primaryClient; 
      this.secondaryClient = secondaryClient; 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      var container = new UnityContainer().LoadConfiguration(); 

      var failOverMessagingClient = container.Resolve<IMessagingClient>("Two"); 

     } 
    } 
} 

вы можете подключить зависимостей с помощью app.config

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 

    <configSections> 
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/> 
    </configSections> 

    <unity xmlns="http://schemas.microsoft.com/practices/2010/unity"> 
    <alias alias="IMessagingClient" type="ConsoleApplication8.IMessagingClient, ConsoleApplication8" /> 
    <alias alias="ServiceBusMessagingClient" type="ConsoleApplication8.ServiceBusMessagingClient, ConsoleApplication8" /> 
    <alias alias="MockMessagingClient" type="ConsoleApplication8.MockMessagingClient, ConsoleApplication8" /> 
    <alias alias="FailoverMessagingClient" type="ConsoleApplication8.FailoverMessagingClient, ConsoleApplication8" /> 
    <container> 
     <register type="IMessagingClient" name="One" mapTo="ServiceBusMessagingClient" /> 
     <register type="IMessagingClient" name="Two" mapTo="FailoverMessagingClient"> 
     <constructor> 
      <param name="primaryClient"> 
      <dependency type="IMessagingClient" name="One" /> 
      </param> 
      <param name="secondaryClient"> 
      <dependency type="IMessagingClient" name="One" /> 
      </param> 
     </constructor> 
     </register> 
    </container> 
    </unity> 

</configuration> 

Изменение линии

<register type="IMessagingClient" name="One" mapTo="ServiceBusMessagingClient" /> 

в

<register type="IMessagingClient" name="One" mapTo="MockMessagingClient" /> 

позволит вам поменять вашу реализацию IMessagingClient соответствующим образом.

Лично я предпочел бы сделать это с помощью синтаксиса жидкости

var container = new UnityContainer(); 
    container.RegisterType<IMessagingClient, ServiceBusMessagingClient>("One"); 

    container.RegisterType<IMessagingClient, FailoverMessagingClient>("Two", 
     new InjectionConstructor(new ResolvedParameter<IMessagingClient>("One"), new ResolvedParameter<IMessagingClient>("One"))); 

    var failOverMessagingClient = container.Resolve<IMessagingClient>("Two"); 
0

При использовании контейнера единства, вы можете изменить существующую регистрацию путем регистрации его снова для другого класса.

Например:

Если запустить этот код:

container.RegisterType<IMessagingClient, ServiceBusMessagingClient>(); 
container.RegisterType<IMessagingClient, MockMessagingClient>(); 

Первая регистрация преодолена и так IMessagingClient сопоставлен MockMessagingClient. Его как первая строка никогда не исполнялась.

Вы можете использовать этот факт, и в тестовом модуле (в аранжировках фазе или в методе настройки вашего тестового класса), просто зарегистрировать IMessagingClient в макете реализации, как это (после загрузки конфигурации XML):

container.RegisterType<IMessagingClient, MockMessagingClient>(); 

Кстати, вы, возможно, не захотите использовать контейнеры DI в модульных тестах. Взгляните на this question.

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