C# IoC:程序集之间的依赖项注入和总体实例

C# IoC:程序集之间的依赖项注入和总体实例,c#,dependency-injection,ioc-container,autofac,service-locator,C#,Dependency Injection,Ioc Container,Autofac,Service Locator,我听说这应该是可能的,但我无法想象这应该如何运作 我正在为我的项目使用依赖注入(autofac)。我和其他人一起开发一个项目,并调用他的类的方法(我使用他的程序集) 然后我得到一个对象的实例,其他人应该使用它进行操作。 我们希望避免在每个方法上传递此对象实例,并使用autofac 他是否可以在不传递任何参数的情况下在组装项目中解析此实例? 我想我们至少要通过DI容器。。。但是我听说依赖注入的概念应该使您能够在整个“执行上下文”中解析对象并得到相同的对象 以下是asp.net web api的示例

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

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

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

他是否可以在不传递任何参数的情况下在组装项目中解析此实例? 我想我们至少要通过DI容器。。。但是我听说依赖注入的概念应该使您能够在整个“执行上下文”中解析对象并得到相同的对象

以下是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;
    }
}
公共类文档控制器:ApiController
{
//获取/api/documents
公共HttpResponseMessage Get()
{
//这里我调用另一个开发者的方法,
//安全/授权应在
//他的方法!
//在此上下文中,WebAPI提供了
//此域中当前用户的IPrincipal
//变量=>“HttpContext.Current.User”,但我们
//不想在每次方法调用时都传递它
ClassFromOtherAssembly.GetDocuments();
HttpResponseMessage响应=
Request.CreateResponse(
HttpStatusCode.OK,文档);
返回响应;
}
}
这是另一个开发人员的类。他应交付文件,并检查用户是否获得授权:

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
        }
    }
}
otherassembly中的公共类
{
公共列表文件()
{
//安全检查
i主要负责人=
DI_容器解析(IPrincipal);
if(委托人IsInRole(“管理”))
{
//返回列表
}
其他的
{
//返回空列表
}
}
}

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

使用带构造函数注入的控制反转通过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
        }
    }
}
otherassembly中的公共类
{
私人知识产权主体;
来自其他程序集的公共类(i主要负责人)
{
this.principal=principal;
}
公共列表文件()
{
//安全检查
if(委托人IsInRole(“管理”))
{
//返回列表
}
其他的
{
//返回空列表
}
}
}

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

使用带构造函数注入的控制反转通过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
        }
    }
}
otherassembly中的公共类
{
私人知识产权主体;
来自其他程序集的公共类(i主要负责人)
{
this.principal=principal;
}
公共列表文件()
{
//安全检查
if(委托人IsInRole(“管理”))
{
//返回列表
}
其他的
{
//返回空列表
}
}
}

不,不要通过容器本身,您将得到一个服务定位器模式,如果您快速搜索,您将了解此模式有一种腐烂的气味

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

    public Foo( IContainer container) //no-no
    {
         this.container = container;
         this.bar = container.Resolve<IBar>();
    }
}
类型在哪个程序集中并不重要。这就是IoC和DI的全部要点——将应用程序的各个部分解耦,使您依赖于抽象,而不是具体的实现


编辑
您误解了DI的服务定位器模式。“我们希望使用依赖注入而不是传递参数”-传递参数是DI,相反,从静态容器解析类型是服务定位器

public class DocumentsController : ApiController
{
    public HttpResponseMessage Get()
    {
        ClassFromOtherAssembly.GetDocuments(); //this is Service locator
        //really bad for testability and maintenance
        ...
    }
}
我看起来像这样

public class DocumentsController : ApiController
{
    private IDocumentProvider;

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

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

不,不要通过容器本身,您将得到一个服务定位器模式,如果您快速搜索,您将了解此模式有一种腐烂的气味

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

    public Foo( IContainer container) //no-no
    {
         this.container = container;
         this.bar = container.Resolve<IBar>();
    }
}
类型在哪个程序集中并不重要。这就是IoC和DI的全部要点——将应用程序的各个部分解耦,使您依赖于抽象,而不是具体的实现


编辑
您误解了DI的服务定位器模式。“我们希望使用依赖注入而不是传递参数”-传递参数是DI,相反,从静态容器解析类型是服务定位器

public class DocumentsController : ApiController
{
    public HttpResponseMessage Get()
    {
        ClassFromOtherAssembly.GetDocuments(); //this is Service locator
        //really bad for testability and maintenance
        ...
    }
}
我看起来像这样

public class DocumentsController : ApiController
{
    private IDocumentProvider;

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

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

不,我不想使用ServiceLocator模式。计划是不通过任何物体。甚至在构造函数中也没有。该类将按时创建,并从不同的方法调用(不同的用户和iPrincipal)中使用,而不是传递我们希望使用依赖注入的参数,以便他获得所需的对象。“服务定位器”的另一个好名称是“依赖提取”,而不是“依赖注入”:-)不,我不想使用ServiceLocator模式。计划是不通过任何物体。甚至在构造函数中也没有。该类将按时创建,并从不同的方法调用(不同的用户和iPrincipal)中使用,而不是传递我们希望使用依赖注入的参数,以便他获得所需的对象。“服务定位器”的另一个好名字是“依赖提取”,而不是“依赖注入”:-)