C# 使用Autofac注册容器本身

C# 使用Autofac注册容器本身,c#,inversion-of-control,autofac,ioc-container,C#,Inversion Of Control,Autofac,Ioc Container,我想知道在容器内部注册是否有任何副作用 IContainer container; ContainerBuilder builder = new ContainerBuilder(); container = builder.Build(); builder.RegisterInstance(container).As<IContainer>(); i集装箱; ContainerBuilder=新的ContainerBuilder(); container=builder.Buil

我想知道在容器内部注册是否有任何副作用

IContainer container;
ContainerBuilder builder = new ContainerBuilder();
container = builder.Build();
builder.RegisterInstance(container).As<IContainer>();
i集装箱;
ContainerBuilder=新的ContainerBuilder();
container=builder.Build();
builder.RegisterInstance(container.As();
然后他们就这样使用它

builder.RegisterType<IManagmentServiceImp>().As<ManagmentServiceImp>()
    .WithParameter(new ResolvedParameter(
            (pi, ctx) => pi.ParameterType == typeof(IContainer) && pi.Name == "Container",
            (pi, ctx) => container
));
builder.RegisterType().As()
.WithParameter(新解析参数(
(pi,ctx)=>pi.ParameterType==typeof(IContainer)和&pi.Name==“容器”,
(pi,ctx)=>容器
));

或者它是否会工作。

由于您需要向
builder.RegisterInstance()
提供容器实例,因此需要在将其作为参数传递之前对其进行初始化,而您目前没有这样做。但是,如果将容器生成器构造为在注册(和容器初始化)后生成,则可以成功解析类中的容器实例

请注意,这肯定是依赖项注入中的一种设计味道,您绝对不应该这样做。容器/内核应该只存在于对象图的顶层。如果您开始注入容器,几乎可以肯定,您正在走向服务定位器反模式

void Main()
{
    IContainer container = new ContainerBuilder().Build();
    ContainerBuilder builder = new ContainerBuilder();

    builder.RegisterInstance(container).As<IContainer>();

    builder.RegisterType<ManagementServiceImp>().As<IManagmentServiceImp>()
       .WithParameter(new ResolvedParameter(
            (pi, ctx) => pi.ParameterType == typeof(IContainer) && pi.Name == "Container",
            (pi, ctx) => container
    ));

    container = builder.Build();
    var instance = container.Resolve<IManagmentServiceImp>();
}

public class ManagementServiceImp : IManagmentServiceImp 
{ 
    private IContainer _container;

    public ManagementServiceImp(IContainer Container)
    {
        _container = Container;
        _container.Dump();
    }
}

public interface IManagmentServiceImp { }
void Main()
{
IContainer container=newcontainerbuilder().Build();
ContainerBuilder=新的ContainerBuilder();
builder.RegisterInstance(container.As();
builder.RegisterType().As()
.WithParameter(新解析参数(
(pi,ctx)=>pi.ParameterType==typeof(IContainer)和&pi.Name==“容器”,
(pi,ctx)=>容器
));
container=builder.Build();
var instance=container.Resolve();
}
公共类ManagementServiceImp:ImanagementServiceImp
{ 
私人集装箱;
公共管理服务IMP(IContainer容器)
{
_容器=容器;
_container.Dump();
}
}
公共接口IManagmentServiceImp{}

您的代码不安全,因为您在初始化实例之前注册了它

如果您需要访问组件内部的容器(这不是一个好主意),您可以依赖具有
Resolve
方法的
ILifetimeScope

public class ManagmentServiceImp 
{
    public ManagmentServiceImp(ILifetimeScope scope)
    {
    }
}
ILifetimeScope
在Autofac中自动注册,您无需为其添加注册

有关更多信息,请参阅Autofac文档中的

顺便说一下,依赖IoC容器不是一个好的做法。看起来你使用了反模式。如果需要容器来延迟加载依赖项,则可以将composition与
Func
lazy

公共类管理服务导入
{
公共管理服务IMP(Lazy myService)
{
这个._myService=myService;
}
私有只读惰性(myService);
}
在这种情况下,当您第一次访问MyService时,将创建它


有关更多信息,请参阅Autofac文档。

您可以使用此扩展方法:

public static void RegisterSelf(this ContainerBuilder builder)
{
    IContainer container = null;
    builder.Register(c => container).AsSelf().SingleInstance();
    builder.RegisterBuildCallback(c => container = c);
}

像这样使用它:
builder.RegisterSelf()

@torvin容器以何种方式未配置?以何种方式无法解决OP的需要?抱歉,我无意中删除了我的评论。它是“这是错误的,它将注册一个未配置的容器”@torvin您还没有解释这如何无法满足OP的需要。容器将是未配置的,因为当您分配新容器
container=builder.Build()时生成器仍将保留对上一个空容器(由新的ContainerBuilder().Build()创建)的引用。您需要使用
Register(Func)
(请参阅我的答案)而不是
RegisterInstance
使用此方法,我得到
指定的CGI应用程序遇到错误,服务器在webapi core中的第一个请求后终止了进程,此后服务器无法处理请求。更改为ILifetimeScope解决了Autofac 5.0的问题,该功能不再有效-更改了
.RegisterBuildCallBack()
的签名,现在提供了
ILifetimeScope
而不是
IContainer
。我仍在寻找一个可行的修复方法。
IContainer
继承自
ILifetimeScope
所以我的作品中有一个演员阵容。。。
public static void RegisterSelf(this ContainerBuilder builder)
{
    IContainer container = null;
    builder.Register(c => container).AsSelf().SingleInstance();
    builder.RegisterBuildCallback(c => container = c);
}