我正在编写一个实用程序类,它将类名和属性名称数组作为这样的参数:
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)
或者,可能更短。有没有办法做到这一点?
答案 0 :(得分:1)
如果你想要语法
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: Retrieving Property name from lambda expression
它可以帮助您避免拼写错误,但会产生其他问题:
// method call
DoMagic<MyClass>(c => c.ToString().Length);
答案 1 :(得分:1)
感谢ASh和Retrieving Property name from lambda expression,我通过解析表达式树来解决我的问题:
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));
简单就像这样!