C# 在需要委托参数的多个重载泛型方法的类上的getmethod中使用的正确签名
在回答了部分问题后,这里有一些额外的信息,希望能够解决仍然存在的问题 开始编辑C# 在需要委托参数的多个重载泛型方法的类上的getmethod中使用的正确签名,c#,reflection,lambda,delegates,methodinfo,C#,Reflection,Lambda,Delegates,Methodinfo,在回答了部分问题后,这里有一些额外的信息,希望能够解决仍然存在的问题 开始编辑 var curEntityPI=ctx.GetType().GetProperties().Where(pr=>pr.Name==“Client”).First(); 类型curEntityType=curEntityPI.PropertyType.GetGenericArguments().First(); Type[]typeArgs={curEntityType}; 类型propertyManagerType=
var curEntityPI=ctx.GetType().GetProperties().Where(pr=>pr.Name==“Client”).First();
类型curEntityType=curEntityPI.PropertyType.GetGenericArguments().First();
Type[]typeArgs={curEntityType};
类型propertyManagerType=generic.MakeGenericType(typeArgs);
var propertyManager=Activator.CreateInstance(propertyManagerType,新对象[]{})代码>
考虑到这一点,我不能使用closeMethod.Invoke,调用的方式与第一个答案中显示的方式相同,我不知道调用时如何放置Func和return体
结束编辑
方法签名对反射来说应该是什么样子,我正在尝试调用与此等效的方法签名
DynamicPropertyManager<ThreeColumns>.CreateProperty<ThreeColumns, string>(
"Four",
t => "Four",
null
));
反射和泛型在一起工作得很好,但是如何实现特定的目标是非常依赖于上下文的,因为可能有封闭的、开放的和部分封闭的类型和方法。尽管如此,使用Linq通常很容易得到您想要的东西。看看:
// get type from somewhere
var compileTimeUnknownType = Type.GetType("ThreeColumns");
if (compileTimeUnknownType == null)
throw new ArgumentException("compileTimeUnknownType");
var managerType = typeof (DynamicPropertyManager<>).MakeGenericType(compileTimeUnknownType);
var createPropertyMethod = managerType.GetMethods().Single(x =>
{
var p = x.GetParameters();
var g = x.GetGenericArguments();
return x.Name == "CreateProperty" &&
p.Length == 3 &&
g.Length == 2 &&
p[0].ParameterType == typeof (string) &&
p[1].ParameterType == typeof (Func<,>).MakeGenericType(g) &&
p[2].ParameterType == typeof (Attribute[]);
});
var closedMethod = createPropertyMethod.MakeGenericMethod(new[] {compileTimeUnknownType, typeof (string)});
var paramExpr = Expression.Parameter(compileTimeUnknownType, "arg");
var lambda =
Expression.Lambda(typeof (Func<,>).MakeGenericType(new[] {compileTimeUnknownType, typeof (string)}),
Expression.Constant("Four"), new List<ParameterExpression>() {paramExpr}).Compile();
var ret = closedMethod.Invoke(null, new object[] {"Four", lambda, null});
//从某处获取类型
var compileTimeUnknownType=Type.GetType(“三列”);
if(compileTimeUnknownType==null)
抛出新ArgumentException(“compileTimeUnknownType”);
var managerType=typeof(DynamicPropertyManager).MakeGenericType(compileTimeUnknownType);
var createPropertyMethod=managerType.GetMethods().Single(x=>
{
var p=x.GetParameters();
var g=x.GetGenericArguments();
返回x.Name==“CreateProperty”&&
p、 长度==3&&
g、 长度==2&&
p[0]。ParameterType==typeof(字符串)&&
p[1]。ParameterType==typeof(Func)。MakeGenericType(g)&&
p[2].ParameterType==typeof(属性[]);
});
var closedMethod=createPropertyMethod.MakeGenericMethod(新[]{compileTimeUnknownType,typeof(string)});
var parametexpr=Expression.Parameter(compileTimeUnknownType,“arg”);
兰姆达变种=
表达式.Lambda(typeof(Func).MakeGenericType(new[]{compileTimeUnknownType,typeof(string)}),
Expression.Constant(“Four”),new List(){paramExpr}).Compile();
var ret=closedMethod.Invoke(null,新对象[]{“四”,lambda,null});
您好,非常感谢您的回复,我认为createPropertyMethod会很好地工作,但我遇到的问题是,我使用反射的原因是ThreeColumns类在运行时之前是未知的。在我的例子中,我附加一个属性的类实际上是另一个泛型类,我通过反射得到了这个泛型类,然后用类类型see edit实例化了propertymanager实例。我修改了代码,现在ThreeColumns
类型不再被编译时引用。非常感谢您查看此内容。我会试一试,然后接受并投票支持你的答案。你真的是个救命恩人,真的!一如所料。我花了一下午的大部分时间独自完成它,我得到了第一个通用位&Expression.Constant的使用,但不是paramExpr位。在我要做的事情中,有一些基本的东西让我困惑不解。非常感谢。
public class DynamicPropertyManager<TTarget> : IDisposable
{
private readonly DynamicTypeDescriptionProvider provider;
private readonly TTarget target;
public DynamicPropertyManager()
{
Type type = typeof(TTarget);
provider = new DynamicTypeDescriptionProvider(type);
TypeDescriptor.AddProvider(provider, type);
}
public DynamicPropertyManager(TTarget target)
{
this.target = target;
provider = new DynamicTypeDescriptionProvider(typeof(TTarget));
TypeDescriptor.AddProvider(provider, target);
}
public IList<PropertyDescriptor> Properties
{
get { return provider.Properties; }
}
public void Dispose()
{
if (ReferenceEquals(target, null))
{
TypeDescriptor.RemoveProvider(provider, typeof(TTarget));
}
else
{
TypeDescriptor.RemoveProvider(provider, target);
}
}
public static DynamicPropertyDescriptor<TTargetType, TPropertyType>
CreateProperty<TTargetType, TPropertyType>(
string displayName,
Func<TTargetType, TPropertyType> getter,
Action<TTargetType, TPropertyType> setter,
Attribute[] attributes)
{
return new DynamicPropertyDescriptor<TTargetType, TPropertyType>(
displayName, getter, setter, attributes);
}
public static DynamicPropertyDescriptor<TTargetType, TPropertyType>
CreateProperty1<TTargetType, TPropertyType>(
string displayName,
Func<TTargetType, TPropertyType> getHandler,
Attribute[] attributes)
{
return new DynamicPropertyDescriptor<TTargetType, TPropertyType>(
displayName, getHandler, (t, p) => { }, attributes);
}
public static DynamicPropertyDescriptor<TTargetType, TPropertyType>
CreateProperty<TTargetType, TPropertyType>(
string displayName,
Func<TTargetType, TPropertyType> getHandler,
Attribute[] attributes)
{
return new DynamicPropertyDescriptor<TTargetType, TPropertyType>(
displayName, getHandler, (t, p) => { }, attributes);
}
}
// get type from somewhere
var compileTimeUnknownType = Type.GetType("ThreeColumns");
if (compileTimeUnknownType == null)
throw new ArgumentException("compileTimeUnknownType");
var managerType = typeof (DynamicPropertyManager<>).MakeGenericType(compileTimeUnknownType);
var createPropertyMethod = managerType.GetMethods().Single(x =>
{
var p = x.GetParameters();
var g = x.GetGenericArguments();
return x.Name == "CreateProperty" &&
p.Length == 3 &&
g.Length == 2 &&
p[0].ParameterType == typeof (string) &&
p[1].ParameterType == typeof (Func<,>).MakeGenericType(g) &&
p[2].ParameterType == typeof (Attribute[]);
});
var closedMethod = createPropertyMethod.MakeGenericMethod(new[] {compileTimeUnknownType, typeof (string)});
var paramExpr = Expression.Parameter(compileTimeUnknownType, "arg");
var lambda =
Expression.Lambda(typeof (Func<,>).MakeGenericType(new[] {compileTimeUnknownType, typeof (string)}),
Expression.Constant("Four"), new List<ParameterExpression>() {paramExpr}).Compile();
var ret = closedMethod.Invoke(null, new object[] {"Four", lambda, null});