我相信我的问题在这里有答案,虽然我不是很清楚我在寻找什么或者我在读什么......而且,不是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概念,虽然这对我来说似乎不对
答案 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
对象,以将其范围限定为单例。
希望这有帮助。