这是Oliver Hanappi在stackoverflow上的posted静态反射代码
private static string GetMemberName(Expression expression)
{
switch (expression.NodeType)
{
case ExpressionType.MemberAccess:
var memberExpression = (MemberExpression)expression;
var supername = GetMemberName(memberExpression.Expression);
if (String.IsNullOrEmpty(supername))
return memberExpression.Member.Name;
return String.Concat(supername, '.', memberExpression.Member.Name);
case ExpressionType.Call:
var callExpression = (MethodCallExpression)expression;
return callExpression.Method.Name;
case ExpressionType.Convert:
var unaryExpression = (UnaryExpression)expression;
return GetMemberName(unaryExpression.Operand);
case ExpressionType.Parameter:
return String.Empty;
default:
throw new ArgumentException("The expression is not a member access or method call expression");
}
}
我有公共包装器方法:
public static string Name<T>(Expression<Action<T>> expression)
{
return GetMemberName(expression.Body);
}
public static string Name<T>(Expression<Func<T, object>> expression)
{
return GetMemberName(expression.Body);
}
然后添加了我自己的方法快捷方式
public static string ClassMemberName<T>(this T sourceType,Expression<Func<T,object>> expression)
{
return GetMemberName(expression.Body);
}
public static string TMemberName<T>(this IEnumerable<T> sourceList, Expression<Func<T,object>> expression)
{
return GetMemberName(expression.Body);
}
需要或利用GetMemberName(Expression expression)
交换机中不同分支的代码示例是什么?什么是这个代码能够强类型?
答案 0 :(得分:3)
许多要求你传递幻数的东西(包含人们有时称之为“魔术字符串”的通用术语)可以使用表达式来提供类型安全。
一个常见的例子是INotifyPropertyChanged
接口的实现。
通常,您的属性设置器包含如下调用:
string _name
public string name
{
get { return _name; }
set
{
if(value.Equals(_name)) return;
_name = value;
OnPropertyChanged("name");
}
}
这里传递字符串“name”以标识已更改的属性。当您的团队主管说“让所有公共属性以大写字母开头......并在其前面添加类名”时,这会变得很糟糕。现在您将属性更改为PersonName
,但您记得将"name"
更改为"PersonName"
的可能性是多少?不高,特别是如果你最初没有编写代码。仍然,该项目将编译,你将花20分钟调试。
相反,您使用表达式:
string _name
public string name
{
get { return _name; }
set
{
if(value.Equals(_name)) return;
_name = value;
OnPropertyChanged(x => x.name);
}
}
...并且您的OnPropertyChanged
实现使用您发布的代码从表达式主体中获取属性的名称。
现在,当您将属性更改为PersonName
时,代码将无法编译,直到您还将表达式更改为读取x => x.PersonName
。这是你的类型安全。
代码显然使用了switch,因为表达式可能包含任何类型的节点;访问属性不一定是MemberExpression
- 它可以引用方法调用,方法的参数等。
如果您只是实现INotifyPropertyChanged
,那么这并非全是必要的,但也许您也在使用它来验证参数或其他内容;该开关只覆盖任何成员访问表达式的基础,如果你给它任何其他东西,则抛出。
答案 1 :(得分:2)
MemberAccess
:foo => foo.SomeField
或foo => foo.SomeProperty
Call
:foo => foo.SomeMethod(...)
Parameter
:foo => foo
Convert
:foo => (int)foo.Something
(也许含蓄)