带有编译检查的属性名作为参数
本文关键字:参数 属性 编译 检查 | 更新日期: 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));
就像这样简单!