c# - 用 lambda 表达式替换字符串作为属性名称

标签 c# generics reflection types

我正在构建自己的属性库,我想检查属性级别是否有属性。目前我有这种方法,效果很好:

    public static bool HasPropertyAttribute<T>(this object instance, string propertyName)
    {
        return Attribute.GetCustomAttributes(instance.GetType().GetProperty(propertyName), typeof(T), true).Any();
    }

现在我正在研究允许我传递 lambda 表达式而不是字符串作为 propertyName 的解决方案。有没有一种优雅的方法可以在不添加此方法的情况下成为依赖于两个泛型类型的方法,又名:

HasPropertyAttribute<T, TProperty>(...).

最佳答案

您可以使用 Lambda 表达式来解析编译时属性引用。 (代码修改自 Retrieving Property name from lambda expression )

public PropertyInfo GetPropertyInfo<TProperty>(
    Expression<Func<TProperty>> propertyLambda)
{
    MemberExpression member = propertyLambda.Body as MemberExpression;
    if (member == null)
        throw new ArgumentException(string.Format(
            "Expression '{0}' refers to a method, not a property.",
            propertyLambda.ToString()));

    PropertyInfo propInfo = member.Member as PropertyInfo;
    if (propInfo == null)
        throw new ArgumentException(string.Format(
            "Expression '{0}' refers to a field, not a property.",
            propertyLambda.ToString()));

    return propInfo;
}

您不需要将其用作扩展方法(尽管如果您想要对其进行调整,您可以,但是除了编写该行外,没有必要拥有源对象实例)

public class Test
{
    public string Prop { get; set; }
}

Test t = new Test();
PropertyInfo propInfo = GetPropertyInfo(() => t.Prop);
Console.WriteLine(propInfo.Name + " -> " + propInfo.PropertyType); //Prop -> System.String

编辑:如果你想拥有一些漂亮的语法并且必须避免拥有对该类型对象的现有引用,你可以这样做:

public static class TypedReflection<TSource>
{
    public static PropertyInfo GetPropertyInfo<TProperty>(
        Expression<Func<TSource, TProperty>> propertyLambda)
    {
        MemberExpression member = propertyLambda.Body as MemberExpression;
        if (member == null)
            throw new ArgumentException(string.Format(
                "Expression '{0}' refers to a method, not a property.",
                propertyLambda.ToString()));

        PropertyInfo propInfo = member.Member as PropertyInfo;
        if (propInfo == null)
            throw new ArgumentException(string.Format(
                "Expression '{0}' refers to a field, not a property.",
                propertyLambda.ToString()));

        return propInfo;
    }
}

然后这样调用它:

PropertyInfo propInfo = TypedReflection<Test>.GetPropertyInfo(o => o.Prop);

此时,添加额外的类型化反射方法(获取方法、字段等)就非常容易了

编辑:它仍然有点依赖于两个泛型类型,但它通过类型推断被隐藏起来了。我更喜欢第二个例子;至少你需要指定声明类的类型(因为你想要类型安全),但你不需要对象实例。它还有一个好处(我怀疑您正在追求),如果您重命名该属性,它会传播到此代码以获取 PropertyInfo

关于c# - 用 lambda 表达式替换字符串作为属性名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13072337/

相关文章:

C# ASP .NET MVC 3单例构造函数调用两次

c# - C# 中的继承 + 嵌套类

java - 如何解释泛型类层次结构中子类的返回值类型和参数定义?

c# - 如何在 C# 中同时迭代两个非平凡类对象的属性,类似于 Python 的 zip 方法

Java世界风: how to access AnalyticSurface on DragEvent

c# - 从 .net 存储 10 - 1 亿个模拟输出的最佳方式(SQL 与平面文件)

c# - WPF WindowChrome : Edges of maximized Window are out of the screen

java - 这个菱形符号的解释?

java - 对 Java 集合使用泛型的意外行为

c# - 从 Nullable 类型反射获取 PropertyType.Name