1

我是依赖注入的新手。我刚刚熟悉了如何使用接口注入实现依赖注入,但我们知道依赖注入可以通过三种方式实现,或者可能更多,它们是:-

  1. 接口注入:服务提供消费者必须实现的接口。该接口在运行时公开特定行为。
  2. Setter 注入:依赖对象公开了一个“setter”方法来注入依赖项。
  3. 构造函数注入:依赖是通过类构造函数注入的

所以我正在寻找一些示例代码,它们可以帮助我了解如何使用 Setter 注入或使用 Unity 的构造函数注入来实现依赖注入。对于实现依赖注入的不同方式的小代码的任何帮助将不胜感激。

我只知道使用统一的接口注入。这是我的代码,它使用统一的接口注入可以正常工作。

public interface ILogger
{
     void Write(string message);
}

We have define three classes as follows.

public class FileLogger : ILogger
{
     public void Write(string message)
     {
          //Do somthing
     }
}

public class SQLLogger : ILogger
{
     public void Write(string message)
     {
          //Do somthing
     }
}

public class WindowsEventLogger : ILogger
{
     public void Write(string message)
     {
          //Do somthing
     }
}

需要在配置文件(即app.config)中注册和映射这些类与接口。

<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 type="UnityTest.ILogger, UnityTest" alias="ILogger" />
    <namespace name="UnityTest"/>

    <container>
      <register mapTo="UnityTest.FileLogger, UnityTest" name="MyFileLogger" type="ILogger"/>
      <register mapTo="UnityTest.SQLLogger, UnityTest" name="MySQLLogger" type="ILogger"/>
      <register mapTo="UnityTest.WindowsEventLogger, UnityTest" name="MyWindowsEventLogger" type="ILogger"/>
    </container>
</unity>

注意:名称属性在注册标签中很重要。

最后我们必须在我们的代码中使用这个映射。因此,我们必须知道哪个更适合特定国家/地区。

字典对象可用于保持此映射如下。

IDictionary<string, string> loggers = new Dictionary<string, string>();
loggers.Add("USA", "MyFileLogger");
loggers.Add("GBR", "MySQLLogger");
loggers.Add("IN", "MyWindowsEventLogger");

您可以从数据库、xml 或其他来源填充​​它,现在是时候调用 Write 方法了。

IUnityContainer container = new UnityContainer();
container.LoadConfiguration();

ILogger logger = container.Resolve<ILogger>(loggers[objUser.countryCode]);
logger.Write("Hello World");

新问题

我找到了一个统一的构造注入示例代码,但仍有一件事不清楚。这是代码。

public class CustomerService
{
  public CustomerService(LoggingService myServiceInstance)
  { 
    // work with the dependent instance
    myServiceInstance.WriteToLog("SomeValue");
  }
} 

IUnityContainer uContainer = new UnityContainer();
CustomerService myInstance = uContainer.Resolve<CustomerService>();

当我们编写时uContainer.Resolve<CustomerService>();,我们没有发送任何 LoggingService 类的实例,那么我们如何创建CustomerService类的实例,因为它的构造函数需要LoggingService.

这个区域不清楚。请向我解释它是如何工作的。

另一个问题是[Dependency]属性:它做什么,以及何时需要用[Dependency]属性修饰方法。

4

2 回答 2

1

以您的代码为基础。

如果您有一些依赖于 ILogger 的类,并且您有 ILogger 的默认注册(没有名称的注册)

IUnityContainer container = new UnityContainer();

//fixed
//by default RegisterType will create new instance of the type every time 
//the container resolves the dependancy 
container.RegisterType<ILogger,SomeLoggerImplementation>();
container.RegisterType<Foo>();
container.RegisterType<Bar>();

//will create a new instance of SomeLoggerImplementation using a default ctor, pass it to the constructor of Foo and return the instance of Foo
//if SomeLoggerImplementation has some other dependancies they can be registered in the container too! 
var foo = container.Resolve<Foo>();

//will create a new instance of SomeLoggerImplementation using a default ctor, create a new instance of Bar, 
//Set the value of the Property Logger (but not the Logger2), and return the instance of Bar
var bar = container.Resolve<Bar>();

//Constructor injection
public class Foo
{
    private ILogger _logger;
    public Foo(ILogger logger)
    {
        //if Foo is resolved from the container , the value for the logger parameter will be provided from the container
        _logger = logger;
    }
}


//property injection
public class Bar
{
    //If Bar is resolvced from the container the value for the Logger property will also  be provided from the container
    [Dependency]
    public ILogger Logger { get; set; }

    //this will not be injected
    public ILogger Logger2 { get; set; }

    public Bar()
    {
    }
}
于 2013-01-21T13:24:28.093 回答
0

首先将要求解的类注册到统一(在这种情况下,将测试类注册到统一)。当您尝试Test使用统一解决类的实例时,它也会解决ILogger。您可以参考msdn 的注入属性

二传手注入;

public class Test : ITest
{
    [Dependency("MyFileLogger")]
    public ILogger Logger
    {
       get { return iLogger; }
       set { iLogger = value; }
    }
}

构造函数注入;

public class Test : ITest
{
    public Test([Dependency("MyFileLogger")] ILogger logger)
    {
         //// you will have an instance of MyFileLogger
    }
}

对于您问题的第二部分,由于LoggingService也已注册到 unity,因此在CustomerService尝试解析时,它将使用构造函数注入来解析LoggingService参数。换句话说,当容器尝试解析时CustomerService;它知道LoggingService需要解决它。然后它首先解析LoggingService参数,然后尝试解析CustomerService

于 2013-01-21T13:24:38.993 回答