是否有一种方法可以获得给定类型的默认比较器,其中类型是可变的,并且只有在运行时才知道?请考虑以下几点:
var RT = typeof(string);
var comparer = EqualityComparer<RT>.Default;这显然不编译,但如果编译了,comparer的值应该与EqualityComparer<string>.Default的值相等。
我认为实现这个目标的唯一方法是制作一个“盒装”比较器,您可以通过反射调用它(见下文)。这是可行的,但相当累赘。有什么更好的方法吗?
澄清,这不是一个好主意,因为反思,但为什么我需要它呢?
所讨论的算法是大型遗留搜索API的一部分。使用者将对象列表(例如,List<Person>)传递给API,在内部创建特定类型的索引(使用反射),以便调用方能够搜索该对象中的任何字段(例如,姓氏)。这通常是不必要的,但在用例中,我正在服务,我们在搜索非常大的集合,而不是其他非常大的集合。为此,数据库存储过程可能更好。但是现在,我需要修补这个遗留API以支持用户定义的比较算法,还需要支持用户选择不提供任何比较算法的情况,在这种情况下,我只知道运行时类型RT。
// Example usage
// Assume "RT" is a Type known only at runtime (e.g., typeof(string))
var box = typeof(BoxedComparer<>);
var generic = box.MakeGenericType(RT);
var specific = (IBoxedComparer) Activator.CreateInstance(generic);
// Now with specific you can get the equality comparer for the runtime type (RT)
var comparer = specific.GetEqualityComparer();
public interface IBoxedComparer
{
// You need the interface to allow a "typeless" cast
EqualityComparer GetEqualityComparer()
}
public BoxedComparer<T> : IBoxedComparer
{
public EqualityComparer GetEqualityComparer() { return EqualityComparer<T>.Default; }
}发布于 2021-01-12 01:29:32
未来的网络搜索者:
反射不是推荐的方法。也许重构是合适的。例如,在以这种方式通过反射创建var comparer之后,还不清楚它将如何实际使用。
为了减轻性能方面的担忧,您可以在创建比较器时缓存它们,就像来源 of EqualityComparer<T>内部为每个T所做的那样。但你的代码就是这样变得更混乱了。
上面说..。
一种简单的、单行完成反射的方法:
var comparer = typeof(EqualityComparer<>).MakeGenericType(RT).GetProperty("Default", BindingFlags.Public | BindingFlags.Static).GetValue(null);其中RT是我们在编译时不知道的运行时Type实例。
要求:
using System.Collections.Generic;
using System.Reflection;注意,当通过反射访问静态字段或属性时,需要将null传递给GetValue/SetValue (通常是传递包含该属性的对象)。
同样,这段代码并不是推荐的方法。可读性、可重用性、维护和错误处理选项并没有得到真正的考虑。这个例子只是展示了一种更简单的方法来获得所需的东西,而不需要引入额外的类。
https://stackoverflow.com/questions/65675797
复制相似问题