Autofac委托工厂使用Func<>

17

我正在尝试理解Autofac中的委托工厂模式。我知道如何使用通过Keyed()注册的IIndex<>实现工厂,这在这里得到了很好的解释:配置定义在抽象类中的Autofac委托工厂

我想知道是否可以使用Func<>创建工厂,以及如何为以下示例进行注册:

public enum Service
{
   Foo,
   Bar
}

public interface FooService : IService 
{
   ServiceMethod();
}

public interface BarService : IService 
{
   ServiceMethod();
}

public class FooBarClient
{
   private readonly IService service;

   public FooBarClient(Func<Service, IService> service)
   {
      this.service = service(Service.Foo);
   }

   public void Process()
   {
      service.ServiceMethod(); // call the foo service.
   }
}

为什么不使用 IIndex<>Keyed() 直接进行注册?Autofac 无法为您创建此 Func<Service, IService>。 您需要在容器中使用 Keyed()Named() 进行注册,例如: builder.Register<Func<Service, IService>>(c => s => c.ResolveKeyed<IService>(s)); 委托工厂只能使用参数创建一种类型,并且不能根据参数选择类型,因为这就是 IIndex<> 的作用。 - nemesv
3
为了使用IIndex<>,我需要引用Autofac库,但我想避免这样做。如果可能的话,我希望我的依赖注入代码仅在组合根(单独的库)中。 - Narayan Akhade
1个回答

22

Autofac无法构造Func<Service, IService>,该函数可让您根据参数返回不同类型的结果。这就是IIndex<>的作用。

但是,如果您不想或不能使用IIndex<>,您可以借助KeyedNamed创建此工厂函数,并在容器中注册您的工厂:

var builder = new ContainerBuilder();
builder.RegisterType<FooBarClient>().AsSelf();
builder.RegisterType<FooService>().Keyed<IService>(Service.Foo);
builder.RegisterType<BarService>().Keyed<IService>(Service.Bar);

builder.Register<Func<Service, IService>>(c => 
{
    var context = c.Resolve<IComponentContext>();
    return s => context.ResolveKeyed<IService>(s);
});

谢谢nemesv!它按预期工作了!!!只有一个问题,IIndex和Func之间会有性能上的差异吗? - Narayan Akhade
我不知道IIndex是如何实现的,以及它具有什么样的缓存或性能优化。您可以检查实现方式,或者需要为您的场景制定性能测试来比较这两个方案。 - nemesv
3
我刚试过使用Reason版本,但它给了我一个“ObjectDisposedException”错误... 我通过在委托内部调用new Foo(这是一个很大的不行之举!)来“解决”这个问题。 - user57508
1
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - felickz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接