有人知道这是否可行?我有一个自定义的Attribute类,它定义了一个为属性实现IComparer的Type。我想通过反射访问该类型并实例化它以便在IEnumerable.OrderBy()中使用:
[System.AttributeUsage(System.AttributeTargets.Property)]
public class SortComparer : System.Attribute
{
public Type ComparerType;
public SortComparer(Type ComparerType)
{
this.ComparerType = ComparerType;
}
}
var property = typeof(PerTurbineResultViewModel).GetProperty(SortColumn);
var sortComparer = property.GetCustomAttributes(typeof(SortComparer), true).FirstOrDefault() as SortComparer;
if (sortComparer != null)
{
var insta = Activator.CreateInstance(sortComparer.ComparerType);
this.Results = lstResults.Select(r => new ResultViewModel(r)).
OrderBy(p => property.GetValue(p, null), insta));
}
以上不编译,因为OrderBy<TSource, TResult>
要求第二个参数为IComparer<TResult>
类型(在编译时未知)。
有没有办法实例化'insta'变量并使用'property'中的类型信息将其转换为IComparer<TResult>
?
编辑: 第一个选项让我非常接近:
Func<ResultViewModel, PropertyInfo> sel = t => property;
this.Results = infoGeneric.Invoke(Results, new object[] { vals, sel, insta }) as IEnumerable<ResultViewModel>;
除了我得到属性选择器的运行时异常:
// Object of type 'System.Func`2[ResultViewModel,System.Reflection.PropertyInfo]' cannot be converted to type 'System.Func`2[ResultViewModel,System.Reflection.RuntimePropertyInfo]'.
RuntimePropertyInfo似乎是内部的...是否有另一种传递属性选择器的方法?
答案 0 :(得分:3)
基本上你有两个选择:
OrderBy
:获取通用方法定义,然后调用MethodInfo.MakeGenericMethod
获取构建的版本,然后调用它。dynamic
让内置的迷你编译器为你做繁重的工作编辑:由于property.GetValue()
仅返回object
,您几乎肯定会 通过反射路径。不管怎样,或者你可以使用第三种,某种可怕但非常容易的选择......
...让所有比较器都实现IComparer<object>
,然后在其中进行转换。那么您的TResult
将为object
,您可以投出:
object tmp = Activator.CreateInstance(sortComparer.ComparerType);
IComparer<object> comparer = (IComparer<object>) tmp;
this.Results = lstResults.Select(r => new ResultViewModel(r))
.OrderBy(p => property.GetValue(p, null), comparer);
答案 1 :(得分:0)
我刚做这个。
Func<T, T, int> compare
参数传递给此类使用工厂方法实例化通用比较器类。
IComparer<Point> comparer = _.CreateComparer<Point>((a, b) =>
{
return (a.X + a.Y) - (b.X + b.Y);
});
comparer.Compare(new Point(0, 0), new Point(0, 0)); // should return zero
comparer.Compare(new Point(100, 0), new Point(0, 0)); // should return a value greater than zero
comparer.Compare(new Point(0, 0), new Point(100, 0)); // should return a value less than zero
这里突出显示了测试方法: