使用Unity设置依赖注入以将类的实例传递给构造函数

时间:2014-07-04 15:37:33

标签: c# asp.net dependency-injection

我相信我的问题在这里有答案,虽然我不是很清楚我在寻找什么或者我在读什么......而且,不是100%确定DI就是我在这种情况下应该使用的。

我正在尝试将Unity用于我的DI。我正在向ASP.Net Web API控制器注入依赖项。到目前为止一切都很好。

我正在向控制器需要的控制器中注入服务。例如,在我的一个控制器中,我有:

private TransactionService _transactionService;

public TransactionsController(TransactionService transactionService)
{
    _transactionService = transactionService;
}

在这种情况下,我将一个TransactionService实例注入控制器。这一切都有效。

我的WebApiConfig.cs包含以下内容,据我所知,它实际上执行了注入:

   var container = new UnityContainer();
   container.RegisterType<ServiceBase>(new HierarchicalLifetimeManager());
   config.DependencyResolver = new UnityResolver(container);

如果需要,我可以告诉你UnityResolver

现在,我正在努力奋斗......

我的服务都继承自抽象类ServiceBase - 最简单的就是这样:

public abstract class ServiceBase : IDisposable
{

    internal Account _account;

    public ServiceBase(){}
} 

我想要做的是在注射过程中创建Account并以某种方式传递它,以便我注入的服务不需要处理帐户的实施。

当我尝试向我的服务添加任何构造函数以接受帐户时,我收到消息以确保我的控制器具有无参数构造函数。

那么..我如何设置我的DI,以便我可以将服务注入我的控制器,并将一个预先实例化的Account实例注入我的服务?

更新

我忘了提及(抱歉Wiktor) - 我想尽可能不使用属性。在我看来,我们可以使用DI解除依赖关系,然后在各处放置一堆依赖属性,这似乎很奇怪。我可能只是没有正确理解DI概念,虽然这对我来说似乎不对

3 个答案:

答案 0 :(得分:0)

这应该很简单,只需将其他属性设为公共,并在其上添加依赖属性。

 [Dependency]  
 public Account _account { get; set; }

Unity应该能够注入属性,你甚至可以用普通的方式注册Account类(例如注入工厂)。

答案 1 :(得分:0)

我希望这会给你一些想法。

为服务基础创建一个接口,并将Acccount声明为公共属性。

您的服务接口:

you can also inherit other interfaces.
public interface ITransactionService : IDisposable
{
  IAccount Account{get;set;}
}

在课堂上实施:

public class TransactionService : ITransactionService{
 private IAccount _account;
 public IAccount Account
 {
   get
     {if(_account==null)_account=new Account(); return _account;}
   set
     {_account=value;}
 }
}

现在使用API​​控制器的构造函数,如下所示:

private ITransactionService _transactionService;

public TransactionsController(ITransactionService transactionService)
{
    _transactionService = transactionService;
}

Unity解析器:

var container = new UnityContainer();
   container.RegisterType<ITransactionService,TransactionService>(new HierarchicalLifetimeManager());
   config.DependencyResolver = new UnityResolver(container);

因此,以这种方式使用属性注入和构造函数注入来减少紧密耦合的依赖。

模拟单元测试界面非常容易。

您还可以为Account类创建一个界面,以便根据您的使用情况轻松进行模拟。

答案 2 :(得分:0)

如果您不想使用我完全同意的属性,最好的方法是让ServiceBase接受帐户参数,例如:

public abstract class ServiceBase {
  private Account _account;

  public ServiceBase(Account account) {
    this._account = account;
  }
}

您必须在派生服务上声明相同的构造函数TransactionService。在实例化控制器时,Unity将首先正确创建Account类的实例,然后通过构造函数注入将其传递给TransactionService对象。您应该使用终身管理器注册Account对象,以将其范围限定为单例。

希望这有帮助。