多层解决方案中的 StructureMap
StructureMap in multi-layer solution
在我的解决方案中,我有 3 个项目:WebAPI、BusinessLayer 和 DataLayer。
在 WebAPI 中,我将结构图配置为使用 DefaultRegistry:
public class DefaultRegistry : Registry
{
public DefaultRegistry()
{
Scan(
scan => {
scan.TheCallingAssembly();
scan.WithDefaultConventions();
});
For<Business.Interfaces.IBusinessClass>().Use(ctx => new Business.BusinessClass());
For<Data.Interfaces.IDataClass>().Use(ctx => new Data.DataClass());
}
}
WebAPI 中的控制器 class 如下所示:
public class MyController : ApiController
{
private readonly IBusinessClass _businessClass;
public MyController(IBusinessClass businessClass)
{
_businessClass = businessClass;
}
public HttpResponseMessage Get(int id)
{
var success = _businessClass.DoSomething();
return success ? Request.CreateResponse(HttpStatusCode.OK) : Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Error");
}
}
在此示例中为 _businessClass 注入依赖项非常有效。
现在让我们看一下 BusinessClass 的实现:
public class BusinessClass : IBusinessClass
{
private readonly IDataClass _dataClass;
public BusinessClass(IDataClass dataClass)
{
_dataClass = dataClass;
}
public void DoSomething()
{
_dataClass.DoSomethingWithData();
}
}
在此示例中,_dataClass 的依赖项注入不起作用。构造函数中的 dataClass 参数为空,因此 _dataClass 字段未正确初始化。我究竟做错了什么?
我要补充一点,BusinessClass 是在 BusinessLayer 项目中定义的,DataClass 是在 DataLayer 项目中定义的(这两个项目都是 class 库)。
问题出在您的注册上:
您只扫描调用程序集(这意味着 Web API 项目)。
您还需要包括其他程序集(您可能需要调整名称):
Scan(
scan => {
scan.TheCallingAssembly();
scan.Assembly("BusinessLayer");
scan.Assembly("DataLayer");
scan.WithDefaultConventions();
});
在您的默认注册表中,您已经通过调用
注册了默认约定
scan.WithDefaultConventions();
所以这两个调用是多余的。
For<Business.Interfaces.IBusinessClass>().Use(ctx => new Business.BusinessClass());
For<Data.Interfaces.IDataClass>().Use(ctx => new Data.DataClass());
正如 Kenneth 所说,您可能没有扫描 BusinessClass
所在的程序集。
public class DefaultRegistry : Registry
{
public DefaultRegistry()
{
Scan(
scan => {
scan.TheCallingAssembly();
scan.AssemblyContainingType<BusinessClass>();
scan.WithDefaultConventions();
});
}
}
我已经通过在 StructureMap 中使用 Singleton 解决了这个问题。
在我的解决方案中,我有 3 个项目:WebAPI、BusinessLayer 和 DataLayer。
在 WebAPI 中,我将结构图配置为使用 DefaultRegistry:
public class DefaultRegistry : Registry
{
public DefaultRegistry()
{
Scan(
scan => {
scan.TheCallingAssembly();
scan.WithDefaultConventions();
});
For<Business.Interfaces.IBusinessClass>().Use(ctx => new Business.BusinessClass());
For<Data.Interfaces.IDataClass>().Use(ctx => new Data.DataClass());
}
}
WebAPI 中的控制器 class 如下所示:
public class MyController : ApiController
{
private readonly IBusinessClass _businessClass;
public MyController(IBusinessClass businessClass)
{
_businessClass = businessClass;
}
public HttpResponseMessage Get(int id)
{
var success = _businessClass.DoSomething();
return success ? Request.CreateResponse(HttpStatusCode.OK) : Request.CreateErrorResponse(HttpStatusCode.BadRequest, "Error");
}
}
在此示例中为 _businessClass 注入依赖项非常有效。
现在让我们看一下 BusinessClass 的实现:
public class BusinessClass : IBusinessClass
{
private readonly IDataClass _dataClass;
public BusinessClass(IDataClass dataClass)
{
_dataClass = dataClass;
}
public void DoSomething()
{
_dataClass.DoSomethingWithData();
}
}
在此示例中,_dataClass 的依赖项注入不起作用。构造函数中的 dataClass 参数为空,因此 _dataClass 字段未正确初始化。我究竟做错了什么? 我要补充一点,BusinessClass 是在 BusinessLayer 项目中定义的,DataClass 是在 DataLayer 项目中定义的(这两个项目都是 class 库)。
问题出在您的注册上:
您只扫描调用程序集(这意味着 Web API 项目)。
您还需要包括其他程序集(您可能需要调整名称):
Scan(
scan => {
scan.TheCallingAssembly();
scan.Assembly("BusinessLayer");
scan.Assembly("DataLayer");
scan.WithDefaultConventions();
});
在您的默认注册表中,您已经通过调用
注册了默认约定scan.WithDefaultConventions();
所以这两个调用是多余的。
For<Business.Interfaces.IBusinessClass>().Use(ctx => new Business.BusinessClass());
For<Data.Interfaces.IDataClass>().Use(ctx => new Data.DataClass());
正如 Kenneth 所说,您可能没有扫描 BusinessClass
所在的程序集。
public class DefaultRegistry : Registry
{
public DefaultRegistry()
{
Scan(
scan => {
scan.TheCallingAssembly();
scan.AssemblyContainingType<BusinessClass>();
scan.WithDefaultConventions();
});
}
}
我已经通过在 StructureMap 中使用 Singleton 解决了这个问题。