C# Autofac将参数传递给嵌套类型

C# Autofac将参数传递给嵌套类型,c#,ioc-container,autofac,C#,Ioc Container,Autofac,我在WCF服务中使用Autofac作为我的IoC。在这种情况下,我希望将对象传递给嵌套类型(即未直接解析的类型,但在解析其他类型时)。据我所知,将此对象作为构造函数参数传递是Autofac中的首选方式。以下是这种情况的一个例子 嵌套类型: public class EventLogger<T> : IEventLogger<T> { public EventLogger(IRepository<T> repository, User currentUs

我在WCF服务中使用Autofac作为我的IoC。在这种情况下,我希望将对象传递给嵌套类型(即未直接解析的类型,但在解析其他类型时)。据我所知,将此对象作为构造函数参数传递是Autofac中的首选方式。以下是这种情况的一个例子

嵌套类型:

public class EventLogger<T> : IEventLogger<T>
{
    public EventLogger(IRepository<T> repository, User currentUser) { ... }  
}
public类事件记录器:IEventLogger
{
公共事件记录器(IRepository存储库,用户currentUser){…}
}
我实际尝试解析的类型:

public class SomeBusinessObject  
{  
    public SomeBusinessObject(IEventLogger<SomeLogEventType> logger, ...) { ... }  
}
公共类SomeBusinessObject
{  
公共SomeBusinessObject(IEventLogger记录器,…{…}
}
注册:

var builder = new ContainerBuilder();
builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>));
builder.RegisterGeneric(typeof(EventLogger<>)).As(typeof(IEventLogger<>));
builder.RegisterType<SomeBusinessObject>();
var builder=newcontainerbuilder();
builder.RegisterGeneric(typeof(Repository)).As(typeof(IRepository));
builder.RegisterGeneric(typeof(EventLogger)).As(typeof(IEventLogger));
RegisterType();
“我的WCF服务”操作中的解决方案:

var currentUser = GetUserFromServiceContext();  
var bo = lifetimeScope.Resolve<SomeBusinessObject>();
var currentUser=GetUserFromServiceContext();
var bo=lifetimeScope.Resolve();
如何以及在何处将当前用户传递到日志记录器?我是否应该假设WCF操作必须知道解析SomeBusinessObject需要首先解析IEventLogger,并在解析SomeBusinessObject时传递已解析的实例?类似这样的事情(如果这不起作用,请原谅,这只是一个想法):

var currentUser=GetUserFromServiceContext();
var logger=lifetimeScope.Resolve(新名称参数(“currentUser”,currentUser));
var bo=lifetimeScope.Resolve(新名称参数(“logger”,logger));

如果这是解决方案,那么如果类型嵌套得更深会发生什么?这难道至少有一点不符合依赖注入的目的吗?

我认为您违反了IOC的原则之一,组件不需要知道其依赖项的依赖项。在您的情况下,容器不知道
SomeBusinessObject
依赖于
User

也就是说,您可以利用Autofac的。您可以手动注册
Func
,以对客户端代码隐藏依赖项链详细信息:

var builder = new ContainerBuilder();
builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>));
builder.RegisterGeneric(typeof(EventLogger<>)).As(typeof(IEventLogger<>));
builder.RegisterType<SomeBusinessObject>();

builder.Register<Func<User, SomeBusinessObject>>(c => {
    // Autofac should be able to resolve these Func<> automatically:
    var loggerFactory = c.Resolve<Func<User, IEventLogger<SomeLogEventType>>>();
    var sboFactory = c.Resolve<Func<IEventLogger<SomeLogEventType>, SomeBusinessObject>>();

        // Now we can chain the Funcs:
    return u => sboFactory(loggerFactory(u));
});
var builder=newcontainerbuilder();
builder.RegisterGeneric(typeof(Repository)).As(typeof(IRepository));
builder.RegisterGeneric(typeof(EventLogger)).As(typeof(IEventLogger));
RegisterType();
builder.Register(c=>{
//Autofac应能够自动解析这些函数:
var loggerFactory=c.Resolve();
var sboFactory=c.Resolve();
//现在我们可以链接函数:
返回u=>sbofacory(loggerFactory(u));
});
现在,在客户端代码中,您可以执行以下操作:

var currentUser = GetUserFromServiceContext();  
var sboFactory = lifetimeScope.Resolve<Func<User, SomeBusinessObject>>();
var bo = sboFactory(currentUser);
var currentUser=GetUserFromServiceContext();
var sboFactory=lifetimeScope.Resolve();
var bo=备用办公室(当前用户);

另外,我认为对lamba/Func的支持使Autofac成为最好的IOC容器。如果你知道如何编写Funcs,你可以做一些非常强大的事情。

谢谢你的回答。你能详细说明我违反国际奥委会原则的事实吗?我同意你的看法,我的最后一个解决办法是,但我不知道为什么你的答案也不一样。我的意思是,您的回答还表明,要构建某个BusinessObject,您需要知道它需要一个用户。我的回答也是:)这是一个解决办法。但是如果我必须按设计使用对象,我会这样做,至少尽可能最好地封装依赖关系。好吧,我明白了!:-)如果你不得不改变物体的设计呢?;-)我对国际奥委会很陌生,我还没有真正了解我的观点……你可以考虑是否有一种方式来登记类型<代码>用户< />代码。我在
builder.Register(c=>HttpContext.Current.User)中使用
IPrincipal
执行类似的操作我明白了。这意味着,每当我有一个
用户
作为参数时,它都会被解析成这样?
var currentUser = GetUserFromServiceContext();  
var sboFactory = lifetimeScope.Resolve<Func<User, SomeBusinessObject>>();
var bo = sboFactory(currentUser);