简体   繁体   中英

How to use autofac register with parameters - the Lambda Expression kind

Autofac documentation

I read the documentation and figured to register a type with parameter I have to make the call this way:

builder.Register((c, p) => new HealthController(c.Resolve<IServiceGroupFactory>(), p.Named<int>("currentServiceGroupId"))).As<IHealthStateController>();

from the example I thought this will register the component together with expectation that there's one int parameter named currentServiceGroupId

but it doesn't seem to work that way

I'm getting "Sequence contains no elements" as autofac is calling IEnumerable.First and trying to find that element in the list. I guess p is empty hence the error.

I'm not sure why it's trying to find it I thought that this syntax will create the sequence and place the parameter it in the IEnumerable collection

So what's the proper way to make this work?

and the finding part is later when resolution happens

stack trace:

at System.Linq.Enumerable.First[TSource](IEnumerable`1 source)
at Autofac.ParameterExtensions.ConstantValue[TParameter,TValue](IEnumerable`1 parameters, Func`2 predicate)
at Autofac.ParameterExtensions.Named[T](IEnumerable`1 parameters, String name)
at NPP.ServiceLayer.ServiceHost.IoCCompositionRoot.<>c.<RegisterExplicitly>b__2_0(IComponentContext c, IEnumerable`1 p) in C:\tfs2012\NPP\Dev\NPP\NPP.ServiceLayer.ServiceHost\App_Start\IoCCompositionRoot.cs:line 116
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()

Autofac's definition for the "Named" extension

public static class ParameterExtensions
{
    /// <summary>
    /// Retrieve a named parameter value from a <see cref="T:Autofac.NamedParameter"/> instance.
    /// 
    /// </summary>
    /// <typeparam name="T">The type to which the returned value will be cast.</typeparam><param name="parameters">The available parameters to choose from.</param><param name="name">The name of the parameter to select.</param>
    /// <returns>
    /// The value of the selected parameter.
    /// </returns>
    /// <seealso cref="T:Autofac.NamedParameter"/>
    public static T Named<T>(this IEnumerable<Parameter> parameters, string name)
    {
      if (parameters == null)
        throw new ArgumentNullException("parameters");
      Enforce.ArgumentNotNullOrEmpty(name, "name");
      return ParameterExtensions.ConstantValue<NamedParameter, T>(parameters, (Func<NamedParameter, bool>) (c => c.Name == name));
    }

private static TValue ConstantValue<TParameter, TValue>(IEnumerable<Parameter> parameters, Func<TParameter, bool> predicate) where TParameter : ConstantParameter
{
  if (parameters == null)
    throw new ArgumentNullException("parameters");
  if (predicate == null)
    throw new ArgumentNullException("predicate");
  return Enumerable.First<TValue>(Enumerable.Cast<TValue>((IEnumerable) Enumerable.Select<TParameter, object>(Enumerable.Where<TParameter>(Enumerable.OfType<TParameter>((IEnumerable) parameters), predicate), (Func<TParameter, object>) (p => p.Value))));
}
}

The Named extension method allows you to retrieve a specific parameter from a collection of Parameter . In your case, you want to create a new parameter, to create a new parameter you can create a new instance of NamedParameter

builder.Register((c, p) => new HealthController(
                               c.Resolve<IServiceGroupFactory>(), 
                               new NamedParameter("currentServiceGroupId", 0))
       .As<IHealthStateController>();

In this case, you don't have to use the lambda Register method, you can use the WithParameters method :

builder.RegisterType<HealthController>()
       .As<IHealthStateController>()
       .WithParameter(new NamedParameter("currentServiceGroupId", 0); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM