多层解决方案中的 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 解决了这个问题。