C# 反射按名称获取字段或属性

问题描述 投票:0回答:3

有没有一种方法可以为函数提供一个名称,然后返回具有该名称的给定对象上的字段或属性的值?我尝试使用 null-coalesce 运算符来解决它,但显然它不喜欢不同的类型(这对我来说也有点奇怪,因为 null 是 null)。我可以将其分离为 if nulls,但必须有更好的方法来做到这一点。这是我的函数,带有

Comparison
对象的两行无法编译,但我会将它们留在那里以显示我正在尝试执行的操作。

private void SortByMemberName<T>(List<T> list, string memberName, bool ascending)
{
   Type type = typeof (T);
   MemberInfo info = type.GetField(memberName) ?? type.GetProperty(memberName);

   if (info == null)
   {
        throw new Exception("Member name supplied is neither a field nor property of type " + type.FullName);
   }

   Comparison<T> asc = (t1, t2) => ((IComparable) info.GetValue(t1)).CompareTo(info.GetValue(t2));
   Comparison<T> desc = (t1, t2) => ((IComparable) info.GetValue(t2)).CompareTo(info.GetValue(t1));

    list.Sort(ascending ? asc : desc);
}

我听说过可以使用动态 LINQ 的东西,但为了学习,我正在按照自己的方式进行。

c# .net reflection null-coalescing-operator
3个回答
18
投票

更改此行:

MemberInfo info = type.GetField(memberName) ?? type.GetProperty(memberName);

对此:

MemberInfo info = type.GetField(memberName) as MemberInfo ??
    type.GetProperty(memberName) as MemberInfo;

因为使用这样的三元运算符时没有隐式转换为基类。三元组要求所有输出的类型相同。


1
投票

C# 9.0 开始,这终于成为可能:

目标已输入?和?:

有时是有条件的?和 ?: 表达式在分支之间没有明显的共享类型。这种情况今天会失败,但如果存在两个分支都转换为的目标类型,C# 9.0 将允许它们:

Person person = student ?? customer; // Shared base type
int? result = b ? 0 : null; // nullable value type

这意味着问题中的代码块也将编译无错误;它将“看到”

FieldInfo
PropertyInfo
有一个共享的基本类型,
MemberInfo

MemberInfo info = type.GetField(memberName) ?? type.GetProperty(memberName);

0
投票

尽管我很喜欢反射(双关语),但这里有一种使用委托属性的替代方法。无需抛出异常,因为这可以确保委托成员的存在。

    private void SortByProperty<T>(List<T> list, Func<T, object> property, bool ascending)
    {
        Comparison<T> asc = (t1, t2) => ((IComparable)property.Invoke(t1)).CompareTo(property.Invoke(t2));
        Comparison<T> desc = (t1, t2) => ((IComparable)property.Invoke(t2)).CompareTo(property.Invoke(t1));

        list.Sort(ascending ? asc : desc);
    }
© www.soinside.com 2019 - 2024. All rights reserved.