2015-10-15 45 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