2

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

我正在为我的项目使用依赖注入(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
        }
    }
}
4

2 回答 2

3

不,不要传递容器本身,您最终会得到一个Service Locator模式,如果您进行快速搜索,您会发现这种模式有一股腐烂的气味。

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
        ...
    }
}
于 2012-07-06T09:44:26.400 回答
1

您通过直接调用 Resolve 来使用 ServiceLocator(反模式)GetDocuments()

使用带有构造函数注入的控制反转来传递 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
        }
    }
}
于 2012-07-06T09:43:59.740 回答