我可以在运行时为OrderBy实例化IComparer类而不管其类型是什么?

时间:2012-08-13 21:09:12

标签: c# reflection ienumerable

有人知道这是否可行?我有一个自定义的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似乎是内部的...是否有另一种传递属性选择器的方法?

2 个答案:

答案 0 :(得分:3)

基本上你有两个选择:

  • 使用反射也调用OrderBy:获取通用方法定义,然后调用MethodInfo.MakeGenericMethod获取构建的版本,然后调用它。
  • 在C#4中使用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)

我刚做这个。

https://github.com/guneysus/underscore.net/blob/67203055348e96857dc5589a3ad4987110b7cc4b/src/underscore.net/Enum.cs#L53-#L56

  1. 定义通用比较器类
  2. Func<T, T, int> compare参数传递给此类
  3. 使用工厂方法实例化通用比较器类。

    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
    

这里突出显示了测试方法:

https://github.com/guneysus/underscore.net/blob/67203055348e96857dc5589a3ad4987110b7cc4b/src/underscore-net-tests/LangTests.cs#L142-#L155