2015-10-15 68 views
1

統一配置我的班級結構簡單,界面如下:與繼承

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> 

我們是否必須使用一些攔截器來實現這一點?或者通過在FailoverMessagingClient中定義一個ctor並使用ctor注入?

一些建議將是偉大的!

回答

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