通过lambda表达式传入时,是否有更好的方法来获取属性名称?这是我现在拥有的.
例如.
GetSortingInfo<User>(u => u.UserId);
Run Code Online (Sandbox Code Playgroud)
只有当属性是字符串时,它才能将其作为元素表达式进行处理.因为不是所有属性都是字符串我必须使用对象,但它会返回一个单一表达式.
public static RouteValueDictionary GetInfo<T>(this HtmlHelper html,
Expression<Func<T, object>> action) where T : class
{
var expression = GetMemberInfo(action);
string name = expression.Member.Name;
return GetInfo(html, name);
}
private static MemberExpression GetMemberInfo(Expression method)
{
LambdaExpression lambda = method as LambdaExpression;
if (lambda == null)
throw new ArgumentNullException("method");
MemberExpression memberExpr = null;
if (lambda.Body.NodeType == ExpressionType.Convert)
{
memberExpr =
((UnaryExpression)lambda.Body).Operand as MemberExpression;
}
else if (lambda.Body.NodeType == ExpressionType.MemberAccess)
{
memberExpr = lambda.Body as MemberExpression;
}
if (memberExpr …Run Code Online (Sandbox Code Playgroud) 它们可以如下使用:
FieldInfo field = fieldof(string.Empty);
MethodInfo method1 = methodof(int.ToString);
MethodInfo method2 = methodof(int.ToString(IFormatProvider));
Run Code Online (Sandbox Code Playgroud)
fieldof 可以编译为IL为:
ldtoken <field>
call FieldInfo.GetFieldFromHandle
Run Code Online (Sandbox Code Playgroud)
methodof 可以编译为IL为:
ldtoken <method>
call MethodBase.GetMethodFromHandle
Run Code Online (Sandbox Code Playgroud)
无论何时使用typeof运算符,您都可以获得完美的查找所有引用结果.不幸的是,一旦你去了田野或方法,你最终会遇到令人讨厌的黑客攻击.我想你可以做以下事情......或者你可以回去按名字命名.
public static FieldInfo fieldof<T>(Expression<Func<T>> expression)
{
MemberExpression body = (MemberExpression)expression.Body;
return (FieldInfo)body.Member;
}
public static MethodInfo methodof<T>(Expression<Func<T>> expression)
{
MethodCallExpression body = (MethodCallExpression)expression.Body;
return body.Method;
}
public static MethodInfo methodof(Expression<Action> expression)
{
MethodCallExpression body = (MethodCallExpression)expression.Body;
return body.Method;
}
public static void Test()
{
FieldInfo field = fieldof(() => string.Empty);
MethodInfo method1 …Run Code Online (Sandbox Code Playgroud) 我经常编写C#代码,必须使用魔术字符串来表达属性名称.每个人都知道魔术弦的问题.它们很难重构,它们没有编译时检查,并且通常会导致难以诊断的问题.然而,C#/ .NET 在整个地方使用它们来表示属性/类/方法名称.
这个问题已持续多年和多年,目前唯一可行的解决方案是使用表达式树,然后在运行时解析属性名称.这使您获得令人满意的编译时检查,但它使代码复杂化(需要Expression类型的参数),并且会产生运行时成本.
有没有人知道是否有一个特性考虑因为C#/ .NET添加编译时反射来克服这个普遍存在的问题?
看起来这将是一个简单的补充,它将是一个非破坏性的变化,它将使许多开发人员受益匪浅.typeof()运算符已经执行了编译时反射的形式,因此看起来运算符nameof()(或类似的东西)将非常互补.
此外,有没有人知道这个功能的任何潜在问题?
谢谢您的帮助.
好.所以我有一些代码将winForm上的某些控件映射到对象中的某些属性,以便在数据发生某些事情时对控件执行某些操作.一切都很好,工作得很好.不是问题.问题是,要将项添加到映射中,我调用的函数看起来像:
this.AddMapping(this.myControl,myObject,"myObjectPropertyName");
Run Code Online (Sandbox Code Playgroud)
我遇到的问题是,在编译时很难说出上述行与下面的行之间的区别:
this.AddMapping(this.myControl,myObject,"myObjectPropretyName");
Run Code Online (Sandbox Code Playgroud)
由于最后一个参数是一个字符串,因此没有编译时检查或类似的任何东西会强制字符串本身实际上对应于给定对象上的有效属性名称.此外,Refactor和"查找所有引用"之类的内容错过了这种引用,当属性名称发生变化时会导致欢闹.所以我想知道的是,是否有某种方法可以更改函数,以便我传入的内容仍然是以某种方式表示属性名称的字符串,但是使用编译时检查实际值是否进入.有人说我可以用Expression Trees做到这一点,但我已经阅读了它们,似乎没有看到连接.我喜欢做类似的事情:
this.AddMapping(this.myControl,myObject,myObject.myObjectPropertyName);
Run Code Online (Sandbox Code Playgroud)
甚至
this.AddMapping(this.myControl,myObject.myObjectPropertyName);
Run Code Online (Sandbox Code Playgroud)
会很甜蜜!
有任何想法吗?
c# ×4
compile-time ×2
reflection ×2
.net ×1
intellisense ×1
lambda ×1
linq ×1
magic-string ×1
mapping ×1