带有编译检查的属性名作为参数

本文关键字:参数 属性 编译 检查 | 更新日期: 2023-09-27 18:13:38

我正在编写一个实用程序类,它以类名和属性名数组作为参数,如下所示:

public static void DoMagic(Type type, params string[] include)

并像这样调用它:

Helper.DoMagic(typeof(MyClass), "ClientId", "PointId", "SerialNumber")

但是我不喜欢它,因为它没有编译检查,如果我在字符串参数中出错,它只会出现运行错误,而不是编译错误。

我想这样做:

Helper.DoMagic<MyClass>(x => x.ClientId, x => x.PointId, x => x.SerialNumber)

或者,可能更短。有什么办法可以做到吗?

带有编译检查的属性名作为参数

语法

Helper.DoMagic<MyClass>(x => x.ClientId, x => x.PointId, x => x.SerialNumber)

你需要声明方法为

public static IEnumerable<FieldInfo> DoMagic<T>(params Expression<Func<T, object>>[] include)
{
    foreach(Expression<Func<T, object>> tree in include)
    {
        FieldInfo fi = null;
        // tree parser, which gets field info
        yield return fi;
    }
}

SO:从lambda表达式中检索属性名

它会帮你避免打字错误,但会产生其他问题:

// method call
DoMagic<MyClass>(c => c.ToString().Length);

多亏了ASh和从lambda表达式中检索属性名,我通过解析表达式树解决了这个问题:

public static class Helper
{
    public static void DoMagic<T>(params Expression<Func<T, object>>[] include) 
    {
        var infos = include.Select(GetPropertyInfo).ToList();
        //do any magic
        foreach (var propertyInfo in infos)
        {
            Console.WriteLine(propertyInfo.Name);
        }
    }
    /// <summary>
    ///     Get PropertyInfo form Expression tree
    /// </summary>
    private static PropertyInfo GetPropertyInfo<TSource, TProperty>(
        Expression<Func<TSource, TProperty>> propertyLambda)
    {
        var type = typeof (TSource);
        var expressionCast = propertyLambda.Body as UnaryExpression;
        // this for boxed types
        var expression = propertyLambda.Body as MemberExpression;

        if (expressionCast == null && expression == null)
        {
            throw new ArgumentException(string.Format(
                "Expression '{0}' is not a MemberExpression ",
                propertyLambda));
        }
        // this for boxed types
        if (expression == null)
        {
            expression = expressionCast.Operand as MemberExpression;
            if (expression == null)
            {
                throw new ArgumentException(string.Format(
                    "Expression '{0}' is not a MemberExpression",
                    propertyLambda));
            }
        }
        var member = expression.Member;
        if (member == null)
            throw new ArgumentException(string.Format(
                "Expression '{0}' refers to a method, not a property.",
                propertyLambda));

        var propInfo = member as PropertyInfo;
        if (propInfo == null)
            throw new ArgumentException(string.Format(
                "Expression '{0}' refers to a field, not a property.",
                propertyLambda));
        if (type != propInfo.ReflectedType &&
            !type.IsSubclassOf(propInfo.ReflectedType))
            throw new ArgumentException(string.Format(
                "Expresion '{0}' refers to a property that is not from type {1}.",
                propertyLambda,
                type));
        return propInfo;
    }
}
public class MyClass
{
    public int ClientId { get; set; }
    public int PointId { get; set; }
    public string SerialNumber { get; set; }
}
internal class Program
{
    private static void Main(string[] args)
    {
        Helper.DoMagic<MyClass>(c => c.ClientId, c => c.PointId, c => c.SerialNumber);
        Console.ReadLine();
    }
}

但是我真正需要的,只是新的c# 6.0特性nameof():

Helper.DoMagic<MyClass>(nameof(myvar.ClientId), nameof(myvar.PointId), nameof(myvar.SerialNumber));

就像这样简单!