我用C#ioc框架弄湿了我的脚。我选择了structuremap.webapi2将集成到现有的API中。我有以下情况,我不确定最好的实施方法是什么。
public class MyController : ApiController
{
public IHttpActionResult MyAction(string clientCode, [FromBody]MyDto bodyData)
{
var client = new ClientManager().GetClientByCode(clientCode);
var someData = new SomeData
{
User = bodyData.User,
ClientCode = clientCode,
SomeField = client.SomeField
};
var myService = new WorkerService(someData);
myService.DoSomething();
return Ok();
}
}
a peek a the WorkerService:
public WorkerService(SomeData someData)
{
_someData = someData;
_someCollection = GetSomeData(); // GetSomeData uses _someData
}
public DoSomething()
{
// some code that uses _someData and _someCollection
}
方法1:
- 使WorkerService的构造函数无参数,并添加一个可以在myController myaction中初始化的公共SomeData属性。
- 那么,IOC可以将客户管理器和WorkerService注入构造函数,以添加到控制器中。
然后,动作看起来像:
public IHttpActionResult MyAction(string clientCode, [FromBody]MyDto bodyData)
{
var client = _clientManager.GetClientByCode(clientCode);
var someData = new SomeData
{
User = bodyData.User,
ClientCode = clientCode,
SomeField = client.SomeField
};
_myService.SomeData = someData;
_myService.DoSomething();
return Ok();
}
方法2(我不确定如何实施(
- 保持工人服务构造函数(带有参数(。将服务注入控制器的构造函数(需要在运行时构建并传递服务的参数(某种程度(,而不是让MyAction Build SomeData(。
- 在每个请求都由控制器处理之前,以某种方式构建某种程度(也许是使用工厂(。这意味着必须以某种方式将客户管理器注射到该工厂。根据请求,IOC将以某种方式使用以某种方式注入控制器的工人服务。
对我来说,方法1似乎更快,更简单,但是方法2似乎更具吸引力,更具挑战性和更多的学习。
我最终找到了解决问题的解决方案:
- 创建一个被动属性并添加到操作
- 创建一个ActionFilter,该操作窗口检查属性并在发现时从请求中获取数据。
- 由于我不喜欢在操作窗中阅读请求主体的方法,因此我更改了请求,并将所需的数据从主体(服务器和数据基名称(移动到请求的URL。然后,我为这些数据创建了一个POCO,并将其注入ActionFilter并用URL数据填充。现在,Poco不可能在需要它的依赖关系链中提供。
-
对于我在某些物体中所需的其余数据,我遵循方法1,使WorkerService的构造函数无参数,并传递了以下数据:
_myService.DoSomething(someData);
-
最后一个技巧是将ActionFilter添加到config.filters.filters,因为我的过滤器具有自己的依赖性,我不能只做:
config.Filters.add(new MyActionFilter(What_About_The_Parametes_???))
我必须获取structureMap的容器实例,并返回我的过滤器实例,这将导致所有依赖项注入其中,然后我可以将过滤器实例添加到config.fign.filters:
: var container = StructuremapMvc.StructureMapDependencyScope.Container;
config.Filters.Add(container.GetInstance<IMyActionFilter>());