Autofac:将装饰器添加到带有参数的委托注册中

时间:2013-03-18 12:08:48

标签: autofac

我正在尝试使用autofac管理我的WCF客户端的注册。

我需要解决Func<MachineEndpoint, IFooService>,因此我使用以下方式注册了服务:

builder.Register((c, p) => FooService(c, p.TypedAs<MachineEndpoint>())).UseWcfSafeRelease()

FooService在哪里:

private IJobService FooService(IComponentContext c, MachineEndpoint endpoint) {...}

这很好用,但我想为此添加一个装饰器来处理某些安全错误,所以我尝试了以下内容:

builder.Register((c, p) => FooService(c, p.TypedAs<MachineEndpoint>())).UseWcfSafeRelease().Named<IFooService>("simple foo service");
builder.RegisterDecorator<IFooService>((c, p, inner) => Wrap(inner, p.TypedAs<MachineEndpoint>(), c.Resolve<CertificateLookupCache>()), "simple foo service");

但是我得到了DependecyResolutionException:

Autofac.Core.DependencyResolutionException: An exception was thrown while executing a resolve operation. See the InnerException for details. ---> System.InvalidOperationException: Sequence contains no elements
   at System.Linq.Enumerable.First[TSource](IEnumerable`1 source)
   at MyModule.<Load>b__4(IComponentContext c, IEnumerable`1 p) in MyModule.cs:line 30 (the first line above)
   at Autofac.Builder.RegistrationBuilder.<>c__DisplayClass1`1.<ForDelegate>b__0(IComponentContext c, IEnumerable`1 p)
   at Autofac.Core.Activators.Delegate.DelegateActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters)
   at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters)
   at Autofac.Core.Resolving.InstanceLookup.Execute()
   at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable`1 parameters)
   at Autofac.Features.LightweightAdapters.LightweightAdapterRegistrationSource.<>c__DisplayClass3.<RegistrationsFor>b__1(IComponentContext c, IEnumerable`1 p)
   at Autofac.Builder.RegistrationBuilder.<>c__DisplayClass1`1.<ForDelegate>b__0(IComponentContext c, IEnumerable`1 p)
   at Autofac.Core.Activators.Delegate.DelegateActivator.ActivateInstance(IComponentContext context, IEnumerable`1 parameters)
   at Autofac.Core.Resolving.InstanceLookup.Activate(IEnumerable`1 parameters)
   at Autofac.Core.Resolving.InstanceLookup.Execute()
   at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable`1 parameters)
   at Autofac.Core.Resolving.ResolveOperation.Execute(IComponentRegistration registration, IEnumerable`1 parameters)
   --- End of inner exception stack trace ---

Server stack trace:
   at Autofac.Core.Resolving.ResolveOperation.Execute(IComponentRegistration registration, IEnumerable`1 parameters)
   at Autofac.Core.Lifetime.LifetimeScope.ResolveComponent(IComponentRegistration registration, IEnumerable`1 parameters)
   at lambda_method(Closure , MachineEndpoint )

如何注册这些函数以便我可以将MachinEndpoint参数传递给WCF客户端对象和装饰器?

1 个答案:

答案 0 :(得分:1)

问题是由您的参数使用引起的:p.TypedAs<MachineEndpoint>()因为Autofac目前存在限制,即RegisterDecorator在创建inner装饰对象时不会传递参数。

因此,当它尝试使用inner创建(c, p) => FooService(c, p.TypedAs<MachineEndpoint>())时,(IEnumerable<Parameter> p)将为空,以便您获得例外。

你基本上可以做两件事:

您可以尝试以不再使用p.TypedAs<MachineEndpoint>()的方式重新组织代码。

或者

因为您的IFooService无论如何都是没有多个实现的WCF服务,您可以通过“手”注册您的Decorator:

builder.Register((c, p) => FooService(c, p.TypedAs<MachineEndpoint>()))
       .UseWcfSafeRelease()
       .Named<IFooService>("simple foo service");
builder.Register<IFooService>((c, p) => 
     Wrap(c.ResolveNamed<IFooService>("simple foo service",
          TypedParameter.From(p.TypedAs<MachineEndpoint>())),
          p.TypedAs<MachineEndpoint>(),
          c.Resolve<CertificateLookupCache>()));
相关问题