如何解决具有List <t>参数的构造函数的类?

时间:2017-03-10 09:47:32

标签: c# generics autofac

我有一个类,如下所示,构造函数有两个List<T>

public  class Param<T>
{
    public List<T> Joes { get; }
    public List<T> Dans { get; }

    public Param(List<T> joes, List<T> dans)
    {
        Joes = joes;
        Dans = dans;
    }
}

我尝试注册并解决此对象,

static void Main(string[] args)
{
    var builder = new ContainerBuilder();
    builder.RegisterType<int>().As<object>();
    builder.RegisterGeneric(typeof(Param<>));
    var container = builder.Build();
    var paramHaha = container.Resolve<Param<object>>();
}

我得到了这个例外

  

在激活特定注册期间发生错误。   有关详细信息,请参阅内部异常注册:Activator = Param&#39; 1   (ReflectionActivator),服务=   [ConsoleApplication2.Param&#39; 1 [[System.Int32,mscorlib,Version = 4.0.0.0,   Culture = neutral,PublicKeyToken = b77a5c561934e089]]],Lifetime =   Autofac.Core.Lifetime.CurrentScopeLifetime,Sharing = None,Ownership   = OwnedByLifetimeScope ---&gt;没有任何构造函数与&#39; Autofac.Core.Activators.Reflection.DefaultConstructorFinder&#39;在类型上   &#39; ConsoleApplication2.Param&#39; 1 [System.Int32]&#39;可以用。调用   可用的服务和参数:\ r \ n无法解析参数   &#39; System.Collections.Generic.List&#39; 1 [System.Int32] joes&#39;构造函数   &#39; Void .ctor(System.Collections.Generic.List&#39; 1 [System.Int32],   System.Collections.Generic.List&#39; 1 [System.Int32])&#39 ;. (见内心   详情除外。)&#34;}

如何解决此问题?我并不十分关心Param的对象是什么,我并不关心T是什么。 Param只是一个在其他地方使用的虚拟对象。但我需要正确初始化它。

2 个答案:

答案 0 :(得分:1)

为了在注册时指定参数值,您可能需要使用WithParameter方法:

builder.RegisterGeneric(typeof(Param<>))
       .As(typeof(Param<>))
       .WithParameter(new ResolvedParameter(
           (pi, ctx) => pi.Name == "joes",
           (pi, ctx) => /* Get joes with pi.ParameterType */)); 

ResolveParameter的第二个参数是一个lambda,它将给出参数的值。因为您使用Param的通用版本,所以必须使用pi.ParameterType属性来获取正确类型的值。

有关详细信息,请参阅Passing Parameters to Register

为了避免在依赖注入注册过程中使用joes检索逻辑,您可以实现JoeProvider

public interface IJoeProvider 
{
    List<Object> GetJoes(); 
}
public interface IJoeProvider<T> : IJoeProvider
{
    List<T> GetJoes(); 
}


builder.RegisterGeneric(typeof(JoeProvider<>)
       .As(typeof(IJoeProvider<>)); 
builder.RegisterGeneric(typeof(Param<>))
       .As(typeof(Param<>))
       .WithParameter(new ResolvedParameter(
           (pi, ctx) => pi.Name == "joes",
           (pi, ctx) => {
               Type t = typeof(IJoeProvider<>).MakeGenericType(pi.ParameterType); 
               IJoeProvider p = (IJoeProvider)ctx.Resolve(t); 
               return p.GetJoes(); 
           }));

当然,为了避免使用JoeProviderDanProvider,您只能拥有一个Provider并使用参数解析它。

public interface IParamProvider 
{
    List<Object> GetParams(); 
}
public interface IParamProvider<T> : IParamProvider
{
    List<T> GetParams(); 
}
public class ParamProvider<T> : IParamProvider<T>
{
    public ParamProvider(String paramName)
    {
        this._paramName = paramName;
    }
    private readonly String _paramName;

    // Do IParamProviderProvider implementation
}


builder.RegisterGeneric(typeof(ParamProvider<>)
       .As(typeof(IParamProvider<>)); 
builder.RegisterGeneric(typeof(Param<>))
       .As(typeof(Param<>))
       .WithParameter(new ResolvedParameter(
           (pi, ctx) => pi.ParameterType.IsGenericType 
                        && pi.ParameterType.GetGenericTypeDefinition() == typeof(List<>),
           (pi, ctx) => {
               Type t = typeof(IParamProvider<>).MakeGenericType(pi.ParameterType); 
               IParamProvider p = (IParamProvider)ctx.Resolve(t, new NamedParameter("paramName", pi.Name)); 
               return p.GetParams(); 
           }));

答案 1 :(得分:1)

您可以将类与参数一起注册,如下所示:

builder.RegisterGeneric(typeof(Param<>)).WithParameters(
    new [] {TypedParameter.From<object>(null), TypedParameter.From<object>(null)});

这只会在您的情况下将空值作为joesdans传递。