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.