使用Unity设置依赖注入,将类的实例传递给构造函数
本文关键字:实例 构造函数 设置 Unity 依赖 注入 使用 | 更新日期: 2023-09-27 18:11:24
我相信这里有我的问题的答案,虽然我只是不太明白我在寻找什么或我正在阅读什么…另外,在这种情况下,我不能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
并以某种方式传递它,以便我注入的服务不需要处理实例化帐户。
当我尝试向我的服务添加任何构造函数以接受Account时,我收到消息以确保我的控制器具有无参数构造函数。
. .我如何设置我的DI,以便我可以注入服务到我的控制器中,并注入Account的预实例化实例到我的服务中?
我忘了说(对不起,Wiktor) -如果可能的话,我不想使用属性。在我看来,这似乎很奇怪,我们可以使用DI来解除依赖,然后到处放置一堆依赖属性。我很可能只是没有正确理解DI的概念,尽管这对我来说似乎不正确
这应该很简单,只需将额外的属性设置为public,并在其上添加依赖属性。
[Dependency]
public Account _account { get; set; }
Unity应该能够注入属性,你甚至可以注册Account
类在一个普通的方式(例如注入工厂)。
我希望这能给你一些启发。
为服务基创建一个接口,并将account声明为公共属性。
服务接口:
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;
}
统一解析器:
var container = new UnityContainer();
container.RegisterType<ITransactionService,TransactionService>(new HierarchicalLifetimeManager());
config.DependencyResolver = new UnityResolver(container);
所以用这种方式使用属性注入和构造函数注入来减少紧耦合依赖。
为单元测试模拟接口是很容易的。
您也可以为Account类创建一个接口,这样就可以很容易地根据您的使用进行模拟。
如果您不想使用属性,我完全同意,最好的方法是让ServiceBase接受account参数,如:
public abstract class ServiceBase {
private Account _account;
public ServiceBase(Account account) {
this._account = account;
}
}
您必须在派生服务上声明相同的构造函数以及TransactionService
。当控制器被实例化时,Unity将首先正确地创建Account
类的实例,然后通过构造函数注入将其传递给TransactionService
对象。您应该使用生命周期管理器注册Account
对象,将其范围设置为单例。