我试图将一个类注册为一个特定的接口,并使用显式类作为其构造函数的参数。问题是它们都实现了相同的接口,当前的注册结束时,Autofac"循环组件依赖检测到#34;。
这是我得到的:
public interface IWorker
{
void DoWork();
}
public class FirstLineWorker : IWorker
{
public void DoWork()
{
//Do some work
}
}
public class SecondLineWorker : IWorker
{
public void DoWork()
{
//Do some morework
}
}
public class SequentialWorker : IWorker
{
private readonly IList<IWorker> _workers;
public SequentialWorker(params IWorker[] workers)
{
_workers = workers;
}
public void DoWork()
{
foreach (var worker in _workers)
{
worker.DoWork();
}
}
}
如何在Autofac中以编程方式将 SequentialWorker 注册为 IWorker ,并使用显式参数 FirstLineWorker 和 SecondLineWorker ?
最初进行循环重新编译的第一次尝试是:
var builder = new ContainerBuilder();
builder
.RegisterType<FirstLineWorker>()
.Named<IWorker>(typeof(FirstLineWorker).Name)
.InstancePerDependency();
builder
.RegisterType<SecondLineWorker>()
.Named<IWorker>(typeof(SecondLineWorker).Name)
.InstancePerDependency();
builder.RegisterType<SequentialWorker>()
.As<IWorker>()
.WithParameter(ResolvedParameter.ForNamed<IWorker>(typeof(FirstLineWorker).Name))
.WithParameter(ResolvedParameter.ForNamed<IWorker>(typeof(SecondLineWorker).Name))
.InstancePerDependency();
有什么想法吗?
答案 0 :(得分:1)
至少有两种方法可供您使用。首先,创建一个新的空接口,派生自IWorker
,如
public interface IWorkExecutor : IWorker { }
然后,注册&#34;正常&#34;工人为IWorker
,&#34;执行人员&#34;作为IWorkExecutor
builder.RegisterType<Worker1>().As<IWorker>();
builder.RegisterType<Worker2>().As<IWorker>();
builder.RegisterType<SequentialWorker>().As<IWorkExecutor>();
第二种方法与您已有的代码非常相似:
containerBuilder.RegisterType<Worker1>().Named<IWorker>(nameof(Worker1));
containerBuilder.RegisterType<Worker2>().Named<IWorker>(nameof(Worker2));
containerBuilder.RegisterType<SequentialWorker>().As<IWorker>()
.WithParameter(new ResolvedParameter(
(pi, cc) => pi.Name == "workers",
(pi, cc) => new [] { cc.ResolveNamed<IWorker>(nameof(Worker1)), cc.ResolveNamed<IWorker>(nameof(Worker2)) }));
您必须在params IWorker[] workers
中传递SequentialWorker
的单个数组参数。
实际上并不需要BTW InstancePerDependency()
,因为这是注册类型时的默认生命周期范围。
答案 1 :(得分:1)
部分由this关于复合模式的问题(这是你在这里实现的)回答。
解决方案是使用通用名称注册所有服务,并在复合注册中解析命名集合:
builder
.RegisterType<FirstLineWorker>()
.Named<IWorker>("worker")
.InstancePerDependency();
builder
.RegisterType<SecondLineWorker>()
.Named<IWorker>("worker")
.InstancePerDependency();
和
builder
.Register<IWorker>(c => new SequentialWorker(
c.ResolveNamed<IEnumerable<IWorker>>("worker").ToArray()))
.As<IWorker>()
.InstancePerDependency();
或
builder.RegisterType<SequentialWorker>()
.As<IWorker>()
.WithParameter(new ResolvedParameter(
(pi, cc) => pi.Name == "workers",
(pi, cc) => cc.ResolveNamed<IEnumerable<IWorker>>("worker").ToArray()));
还值得一提的是params
并非真正需要,您可以使用IEnumerable
,因为它无需在解析ToArray()
时执行"worker"
public SequentialWorker(IEnumerable<IWorker> workers)
{
_workers = workers;
}