IoC:依赖注入和程序集之间的整体实例

时间:2012-07-06 09:20:29

标签: c# dependency-injection ioc-container autofac service-locator

我听说这应该是可能的,但我无法想象它应该如何运作。

我正在为我的项目使用依赖注入(autofac)。我和其他人一起开发了一个项目并调用了他的类的方法(我使用他的程序集)。

然后我得到一个对象的实例,另一个人应该用它来进行操作。 我们希望避免在每个方法上传递此对象实例并使用autofac。

他可以在没有传递任何参数的情况下在他的装配项目中解析此实例吗? 我认为我们必须至少传递DI-Container ......但是我听说依赖注入的概念应该可以解决整个“执行上下文”中的对象并获得相同的对象。

这是asp.net web api的一个例子:

这是asp.net webapi项目的api控制器:

public class DocumentsController : ApiController
{
    // GET /api/documents
    public HttpResponseMessage Get()
    {
        // Here I call the method of the other developer, 
        // security/authorization should be handled in 
        // his method!
        // In this context the WebAPI provides the 
        // IPrincipal of the current user in this 
        // variable => "HttpContext.Current.User" but we 
        // don't want to pass it on every method call
        ClassFromOtherAssembly.GetDocuments();

        HttpResponseMessage response = 
            Request.CreateResponse<IEnumerable<Document>>(
                HttpStatusCode.OK, documents);

        return response;
    }
}

这是其他开发者的类。他应该提交文件并检查用户是否有权:

public class ClassFromOtherAssembly
{
    public List<Documents> GetDocuments()
    {
        //Security check
        IPrincipal principal = 
            DI_Container.Resolve(IPrincipal);

        if(principal.IsInRole("Admin"))
        {
            //return the list
        }
        else
        {
            //return empty list
        }
    }
}

2 个答案:

答案 0 :(得分:3)

不,不要通过容器本身,你最终会得到一个服务定位器模式,如果你进行快速搜索,你就会明白这种模式有腐烂的气味。

public class Foo
{
    private IContainer container;
    private IBar bar;

    public Foo( IContainer container) //no-no
    {
         this.container = container;
         this.bar = container.Resolve<IBar>();
    }
}

而是使用适当的DI,例如

public class Foo
{
    private IBar bar;

    public Foo(IBar bar)
    {
        this.bar = bar;
    }
}

您的类型在哪种汇编中并不重要。这是IoC和DI的重点 - 解耦部分应用程序并使您依赖于抽象,而不是具体的实现。

<小时/> 的修改
您误解了DI的服务定位器模式。 “而不是传递我们想要使用依赖注入的参数” - 传递参数是DI,相反,从静态容器中解析类型是服务定位器。

public class DocumentsController : ApiController
{
    public HttpResponseMessage Get()
    {
        ClassFromOtherAssembly.GetDocuments(); //this is Service locator
        //really bad for testability and maintenance
        ...
    }
}

DI看起来像这样

public class DocumentsController : ApiController
{
    private IDocumentProvider;

    public DocumentsController(IDocumentProvider provider)
    {
        this.provider = provider;
    }

    public HttpResponseMessage Get()
    {
        provider.GetDocuments(); //this is DI
        ...
    }
}

答案 1 :(得分:1)

您正在使用ServiceLocator(反模式)直接从GetDocuments()

调用Resolve

使用构造函数注入的控制反转来传递IPrinciple:

public class ClassFromOtherAssembly
{
    private IPrincipal principal;

    public ClassFromOtherAssembly(IPrincipal principal)
    {
        this.principal = principal;
    }

    public List<Documents> GetDocuments()
    {
        //Security check
        if (principal.IsInRole("Admin"))
        {
            //return the list
        }
        else
        {
            //return empty list
        }
    }
}