C# 我是否可以在运行时为OrderBy实例化IComparer类,而不考虑其类型?

C# 我是否可以在运行时为OrderBy实例化IComparer类,而不考虑其类型?,c#,reflection,ienumerable,C#,Reflection,Ienumerable,有人知道这是否可能吗?我有一个自定义属性类,它定义了一个为属性实现IComparer的类型。我希望通过反射访问该类型,并将其实例化以在IEnumerable.OrderBy()中使用: 由于OrderBy要求第二个参数的类型为IComparer(编译时未知),因此无法编译上述参数 是否有方法使用“property”中的类型信息实例化“insta”变量并将其转换为IComparer 编辑: 第一个选项让我非常接近: Func<ResultViewModel, PropertyInfo>

有人知道这是否可能吗?我有一个自定义属性类,它定义了一个为属性实现IComparer的类型。我希望通过反射访问该类型,并将其实例化以在IEnumerable.OrderBy()中使用:

由于
OrderBy
要求第二个参数的类型为
IComparer
(编译时未知),因此无法编译上述参数

是否有方法使用“property”中的类型信息实例化“insta”变量并将其转换为
IComparer

编辑: 第一个选项让我非常接近:

Func<ResultViewModel, PropertyInfo> sel = t => property;

this.Results = infoGeneric.Invoke(Results, new object[] { vals, sel, insta }) as IEnumerable<ResultViewModel>;

RuntimePropertyInfo似乎是内部的。。。是否有其他方法传入属性选择器?

基本上,您有两个选项:

  • 同样使用反射调用
    OrderBy
    :获取泛型方法定义,然后调用以获取构造的版本,然后调用它
  • 在C#4中使用
    dynamic
    ,让内置的迷你编译器为您完成繁重的工作
编辑:由于
property.GetValue()
只返回
object
,因此几乎肯定要通过反射路径。或者你可以用第三个,在某个可怕但非常简单的地方

。。。让所有比较器实现
IComparer
,并在其中强制转换。然后您的
TResult
将是
对象
,您可以直接强制转换:

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);
object tmp=Activator.CreateInstance(sortComparer.ComparerType);
IComparer comparer=(IComparer)tmp;
this.Results=lstreults.Select(r=>newresultviewmodel(r))
.OrderBy(p=>property.GetValue(p,null),比较器);

有时最好使用函数方法,通过工厂函数实例化帮助器类

  • 实现
    IComparer
    接口[]的泛型类

    内部类GenericEqualityComparer:IEqualityComparer
    {
    专用只读函数比较器;
    公共通用质量比较程序(功能比较程序){
    _比较器=比较器;
    }
    公共布尔等于(TX,TY)
    {
    返回比较器(x,y);
    }
    公共int GetHashCode(T obj)
    {
    返回base.GetHashCode();
    }
    }
    
  • 使用工厂方法实例化泛型比较器类[],并将
    Func compare
    delegate作为参数传递给该类

      IComparer<Point> comparer = comparator<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
    
    IComparer comparer=比较器((a,b)=>
    {
    回报率(a.X+a.Y)-(b.X+b.Y);
    });
    comparer.Compare(新点(0,0),新点(0,0));//应该返回零
    comparer.Compare(新点(100,0),新点(0,0));//应返回大于零的值
    comparer.Compare(新点(0,0),新点(100,0));//应返回小于零的值
    

我以前被调用过很多东西,但“ComparerType”是一个新的:)您的第一个选项让我非常接近:还有第三个选项-您可以使用相同的反射信息来构建动态LINQ表达式树,该树只需使用MethodInfo指定的方法即可。IIRC,结果将比通过反射调用运行得更快,明显快于使用“动态”的方法,并且只比基于使用IL发射器的动态发射具体热固定方法的解决方案稍微慢一点。如果你对此“爆炸式”表达感兴趣,从ie开始。gist已经不存在了。出于历史目的,应该在帖子中包含代码
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);
internal class GenericEqualityComparer<T> : IEqualityComparer<T>
{
  private readonly Func<T, T, bool> _comparer;

  public GenericEqualityComparer(Func<T, T, bool> comparer) {
      _comparer = comparer;
  }

  public bool Equals(T x, T y)
  {
      return _comparer(x, y);
  }

  public int GetHashCode(T obj)
  {
      return base.GetHashCode();
  }
}
  IComparer<Point> comparer = comparator<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