C# 如何使用具有列表的构造函数解析类<;T>;参数
我有一个类,如下所示,构造函数接受两个C# 如何使用具有列表的构造函数解析类<;T>;参数,c#,generics,autofac,C#,Generics,Autofac,我有一个类,如下所示,构造函数接受两个List 公共类参数 { 公共列表作业{get;} 公共列表数据{get;} 公共参数(列表作业、列表数据) { Joes=Joes; Dans=Dans; } } 我尝试注册并解析此对象 static void Main(string[] args) { var builder = new ContainerBuilder(); builder.RegisterType<int>().As<object>();
List
公共类参数
{
公共列表作业{get;}
公共列表数据{get;}
公共参数(列表作业、列表数据)
{
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>>();
}
static void Main(字符串[]args)
{
var builder=new ContainerBuilder();
builder.RegisterType().As();
建造商注册通用(类型(参数));
var container=builder.Build();
var paramHaha=container.Resolve();
}
我得到了这个例外
激活特定注册时发生错误。
有关详细信息,请参见内部异常。注册:激活器=参数'1
(反射激活器),服务=
[ConsoleApplication2.Param'1[[System.Int32,mscorlib,版本=4.0.0.0,
区域性=中性,PublicKeyToken=b77a5c561934e089]]],生存期=
Autofac.Core.Lifetime.CurrentScopeLifetime,共享=无,所有权
=OwnedByLifetimeScope-->在类型上找不到具有“Autofac.Core.Activators.Reflection.DefaultConstructorFinder”的构造函数
“ConsoleApplication2.Param”1[System.Int32]”可以通过调用
可用服务和参数:\r\n无法解析参数
构造函数的'System.Collections.Generic.List'1[System.Int32]joes'
'Void.ctor(System.Collections.Generic.List'1[System.Int32],
System.Collections.Generic.List'1[System.Int32])。(见内文)
详细信息除外。)“}
如何解决此问题?我不关心为
Param
获取的对象是什么,也不关心t
是什么。Param
只是一个虚拟对象,可以在其他地方使用。但我需要正确初始化它。为了在注册时指定参数值,您可能需要使用带参数的方法:
builder.RegisterGeneric(typeof(Param<>))
.As(typeof(Param<>))
.WithParameter(new ResolvedParameter(
(pi, ctx) => pi.Name == "joes",
(pi, ctx) => /* Get joes with pi.ParameterType */));
当然,为了避免使用JoeProvider
和DanProvider
,您只能使用一个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();
}));
公共接口iparmprovider
{
列出GetParams();
}
公共接口iparmprovider:iparmprovider
{
列出GetParams();
}
公共类ParamProvider:iparmprovider
{
公共参数提供程序(字符串参数名)
{
这是。_paramName=paramName;
}
私有只读字符串_paramName;
//是否执行IParmProviderProvider实现
}
builder.RegisterGeneric(typeof(ParamProvider)
.As(类型(IParamProvider));
生成器注册表通用(类型(参数))
.As(类型(参数))
.WithParameter(新解析参数(
(pi,ctx)=>pi.ParameterType.IsGenericType
&&pi.ParameterType.GetGenericTypeDefinition()==typeof(列表),
(pi,ctx)=>{
类型t=typeof(iparmprovider).MakeGenericType(pi.ParameterType);
iparmprovider p=(iparmprovider)ctx.Resolve(t,新名称参数(“paramName”,pi.Name));
返回p.GetParams();
}));
您可以将类与参数一起注册,如下所示:
builder.RegisterGeneric(typeof(Param<>)).WithParameters(
new [] {TypedParameter.From<object>(null), TypedParameter.From<object>(null)});
builder.RegisterGeneric(typeof(Param))。带参数(
新[]{TypedParameter.From(null),TypedParameter.From(null)});
在您的情况下,这将只作为joes
和dans
传递空值。应该为joes
和dans
注入什么?一个随机列表?@YacoubMassad,是的。如果您不关心为这两个列表注入什么,只需为该参数创建无参数构造函数即可。@Evk,假设我无法创建参数ss构造函数。在我看来,您滥用DI容器来构建包含运行时状态的对象的对象图。这不是DI容器的用途。它们的工作是构建应用程序组件的对象图。组件是包含应用程序行为的类,而不是数据。
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();
}));
builder.RegisterGeneric(typeof(Param<>)).WithParameters(
new [] {TypedParameter.From<object>(null), TypedParameter.From<object>(null)});