我已经尝试了我能找到的其他人使用的所有变体,坦率地说,它们似乎都归结为我已经拥有的。
我想要一个泛型系统来调用基于泛型输入的方法。我不确定这是否真的完全抓住了它,但我不知道该如何表述。
我想从表达式>
的参数中生成面包屑这里,selecteddivisations是ObservableCollection, ModelId是long?关键是,我想输入一系列不同的属性,让它们由数据类处理每个属性都由data
中相应的方法处理data.MakeBreadCrumbs(() => dc.SelectedDivisions, () => dc.ModelId);
data包含以下代码:
public void MakeBreadCrumbs(params Expression<Func<object>>[] propertyExpressions) {
foreach (Expression<Func<object>> propertyExpression in propertyExpressions) {
MemberExpression member = propertyExpression.Body as MemberExpression;
if (member == null) {
UnaryExpression uExp = propertyExpression.Body as UnaryExpression;
member = uExp.Operand as MemberExpression;
}
PropertyInfo propInfo = member.Member as PropertyInfo;
Type[] propTypes = propInfo.PropertyType.GetGenericArguments();/
MethodInfo methodInfo = typeof(BreadcrumbData).GetGenericMethod("MakeBreadCrumb", new Type[] { propInfo.PropertyType, typeof(string) }); //
if (methodInfo.IsGenericMethod) {
methodInfo.MakeGenericMethod(propTypes[0]);
}
ConstantExpression ce = Expression.Constant(propertyExpression.Compile().Invoke());
string criterionName = ReadCriterionName(propertyExpression);
methodInfo.Invoke(this, new object[] { ce.Value, criterionName });
}
最后一行失败,"不能对ContainsGenericParameters为真的类型或方法执行延迟绑定操作",当我处理ObservableCollection项的属性表达式时。
下面是数据类中定义的方法,它们是可用的,并且是正确选择的,但是用于ObservableCollection的方法在调用时失败
(LookupTypeBase是一个特定于我的解决方案的类,但在这里插入任何类型,与伪ObservableCollection属性的类型一起工作)
public void MakeBreadCrumb<T>(ObservableCollection<T> selections, string criterionName) where T : LookupTypeBase {...}
public void MakeBreadCrumb(long? value, string criterionName) {...}
public static class xxx {
public static MethodInfo GetGenericMethod(this Type type, string name, Type[] parameterTypes) {
var methods = type.GetMethods();
foreach (var method in methods.Where(m => m.Name == name)) {
var methodParameterTypes = method.GetParameters().Select(p => p.ParameterType).ToArray();
if (methodParameterTypes.SequenceEqual(parameterTypes, new SimpleTypeComparer())) {
return method;
}
}
return null;
}
private class SimpleTypeComparer : IEqualityComparer<Type> {
public bool Equals(Type x, Type y) {
return x.Assembly == y.Assembly && x.Namespace == y.Namespace && x.Name == y.Name;
}
public int GetHashCode(Type obj) {
throw new NotImplementedException();
}
}
}
这是silverlight 4,所以你可以使用动态关键字来调用后绑定方法,这应该会使这变得简单和快速:
BreadcrumbData.MakeBreadCrumb((dynamic)ce.Value, (dynamic)criterionName);
除此之外,我认为你的问题是MakeGenericMethod
返回一个新的methodinfo
,你忽略了它,而不是像这样保持:
if (methodInfo.IsGenericMethod) {
methodInfo = methodInfo.MakeGenericMethod(propTypes[0]);
}