如何通过反射获取当前属性名称?
Posted
技术标签:
【中文标题】如何通过反射获取当前属性名称?【英文标题】:How to get current property name via reflection? 【发布时间】:2010-11-15 09:58:45 【问题描述】:我想通过反射机制获取属性名称。有可能吗?
更新: 我有这样的代码:
public CarType Car
get return (Wheel) this["Wheel"];
set this["Wheel"] = value;
因为我需要更多这样的属性,所以我想做这样的事情:
public CarType Car
get return (Wheel) this[GetThisPropertyName()];
set this[GetThisPropertyName()] = value;
【问题讨论】:
+1 我在实现 System.Configuration.ApplicationSettingsBase 时也想知道这个 【参考方案1】:方式#1
var a = nameof(SampleMethod); //a == SampleMethod
var b = nameof(SampleVariable); //b == SampleVariable
var c = nameof(SampleProperty); //c == SampleProperty
方式#2
MethodBase.GetCurrentMethod().Name; // Name of method in which you call the code
MethodBase.GetCurrentMethod().Name.Replace("set_", "").Replace("get_", ""); // current Property
方式#3
来自 StackTrace:
public static class Props
public static string CurrPropName =>
(new StackTrace()).GetFrame(1).GetMethod().Name.Replace("set_", "").Replace("get_", "");
public static string CurrMethodName =>
(new StackTrace()).GetFrame(1).GetMethod().Name;
您只需致电Props.CurrPropName
或Props.CurrMethodName
方式#4
.NET 4.5+ 的解决方案:
public static class Props
public static string GetCallerName([System.Runtime.CompilerServices.CallerMemberName] String propertyName = "")
return propertyName;
usgae:Props.GetCallerName();
【讨论】:
【参考方案2】:您提供的示例有点令人困惑,除非我只是不明白。
从 C# 6.0 开始,您可以使用 nameof
运算符。
public CarType MyProperty
get return (CarType)this[nameof(MyProperty)];
set this[nameof(MyProperty)] = value];
如果您有一个方法可以处理您的 getter/setter,您可以使用 C# 4.5 CallerMemberName
属性,在这种情况下您甚至不需要重复名称。
public CarType MyProperty
get return Get<CarType>();
set Set(value);
public T Get<T>([CallerMemberName]string name = null)
return (T)this[name];
public void Set<T>(T value, [CallerMemberName]string name = null)
this[name] = value;
【讨论】:
我每次都忘记nameof
的魔力。这比我看到的所有其他解决方案更容易调用nameof(property)
。确认只是做nameof(item.PropertyName)
对我来说就像一种魅力。尽管其他人的情况可能会有所不同。
@Niklas nameof
是 C# 有史以来最伟大的语法改进之一。使在代码中使用文字字符串几乎过时,从而不仅提高了便利性,而且提高了代码安全性。我一直在使用它。【参考方案3】:
尝试使用System.Diagnostics.StackTrace
反映调用堆栈。该属性应位于调用堆栈中的某个位置(如果您直接从该属性的代码中调用它,则可能位于顶部)。
【讨论】:
【参考方案4】:FWIW 我实现了一个这样的系统:
[CrmAttribute("firstname")]
public string FirstName
get return GetPropValue<string>(MethodBase.GetCurrentMethod().Name);
set SetPropValue(MethodBase.GetCurrentMethod().Name, value);
// this is in a base class, skipped that bit for clairty
public T GetPropValue<T>(string propName)
propName = propName.Replace("get_", "").Replace("set_", "");
string attributeName = GetCrmAttributeName(propName);
return GetAttributeValue<T>(attributeName);
public void SetPropValue(string propName, object value)
propName = propName.Replace("get_", "").Replace("set_", "");
string attributeName = GetCrmAttributeName(propName);
SetAttributeValue(attributeName, value);
private static Dictionary<string, string> PropToAttributeMap = new Dictionary<string, string>();
private string GetCrmAttributeName(string propertyName)
// keyName for our propertyName to (static) CrmAttributeName cache
string keyName = this.GetType().Name + propertyName;
// have we already done this mapping?
if (!PropToAttributeMap.ContainsKey(keyName))
Type t = this.GetType();
PropertyInfo info = t.GetProperty(propertyName);
if (info == null)
throw new Exception("Cannot find a propety called " + propertyName);
object[] attrs = info.GetCustomAttributes(false);
foreach (object o in attrs)
CrmAttributeAttribute attr = o as CrmAttributeAttribute ;
if (attr != null)
// found it. Save the mapping for next time.
PropToAttributeMap[keyName] = attr.AttributeName;
return attr.AttributeName;
throw new Exception("Missing MemberOf attribute for " + info.Name + "." + propertyName + ". Could not auto-access value");
// return the existing mapping
string result = PropToAttributeMap[keyName];
return result;
还有一个名为 CrmAttributeAttribute 的自定义属性类。
我强烈建议反对使用 GetStackFrame() 作为解决方案的一部分,我原来的解决方案版本更简洁:
return GetPropValue<string>();
但它比上面的版本慢了 600 倍。
【讨论】:
【参考方案5】:我想更多地了解您需要它的上下文,因为在我看来,您应该已经知道您在属性访问器中使用的属性。但是,如果必须,您可以使用MethodBase.GetCurrentMethod().Name 并删除get_/set_
之后的任何内容。
更新:
根据您的更改,我会说您应该使用继承而不是反射。我不知道您的字典中有哪些数据,但在我看来,您确实希望拥有不同的 Car 类,例如 Sedan、Roadster、Buggy、StationWagon,而不是将类型保存在局部变量中。然后,您将拥有为该类型的 Car 执行正确操作的方法的实现。无需找出您拥有的汽车类型,然后执行某项操作,您只需调用适当的方法,Car 对象就会根据它的类型做正确的事情。
public interface ICar
void Drive( decimal velocity, Orientation orientation );
void Shift( int gear );
...
public abstract class Car : ICar
public virtual void Drive( decimal velocity, Orientation orientation )
...some default implementation...
public abstract void Shift( int gear );
...
public class AutomaticTransmission : Car
public override void Shift( int gear )
...some specific implementation...
public class ManualTransmission : Car
public override void Shift( int gear )
...some specific implementation...
【讨论】:
我添加了更多关于我的上下文的解释。 您的更新只是说明了为什么您不应该尝试使用反射。使用建议的反射方式,您最终可能会发现您在“GetThisPropertyName”中,并决定您是“ThisPropertyName”属性。您将不得不调整示例以“向下”进行一次堆栈调用,以便获得实际的属性调用。虽然有可能,但它看起来有点矫枉过正。您的代码将洒满 this[GetThisPropertyName()] 调用的复制/粘贴,并且不再可读(恕我直言)。我个人会坚持使用普通的字符串 dict 访问器。【参考方案6】:由于属性实际上只是方法,因此您可以执行此操作并清理返回的 get_:
class Program
static void Main(string[] args)
Program p = new Program();
var x = p.Something;
Console.ReadLine();
public string Something
get
return MethodBase.GetCurrentMethod().Name;
如果您分析性能,您应该会发现 MethodBase.GetCurrentMethod() 比 StackFrame 快几英里。在 .NET 1.1 中,您还会遇到 StackFrame 在释放模式下的问题(从内存中我认为我发现它快了 3 倍)。
也就是说,我确信性能问题不会造成太大问题 - 尽管有关 StackFrame 缓慢的有趣讨论可以是 found here。
如果您担心性能,我想另一种选择是创建一个 Visual Studio Intellisense 代码片段,它为您创建属性并创建一个与属性名称对应的字符串。
【讨论】:
有趣——我不知道 GetCurrentMethod()Properties
你有类似的吗?【参考方案7】:
改用 MethodBase.GetCurrentMethod()!
反射用于处理无法在编译时完成的类型。获取您所在的属性访问器的名称可以在编译时决定,因此您可能不应该对其使用反射。
不过,您可以使用 System.Diagnostics.StackTrace
从调用堆栈中使用访问器方法的名称。
string GetPropertyName()
StackTrace callStackTrace = new StackTrace();
StackFrame propertyFrame = callStackTrace.GetFrame(1); // 1: below GetPropertyName frame
string properyAccessorName = propertyFrame.GetMethod().Name;
return properyAccessorName.Replace("get_","").Replace("set_","");
【讨论】:
我一直在做这样的事情,但它让我又回来了。请注意,如果内联属性可能会导致问题:将 [MethodImpl(MethodImplOptions.NoInlining)] 放在 getter/setter 之前会有所帮助,但不方便......【参考方案8】:是的!
string test = "test string";
Type type = test.GetType();
PropertyInfo[] propInfos = type.GetProperties();
for (int i = 0; i < propInfos.Length; i++)
PropertyInfo pi = (PropertyInfo)propInfos.GetValue(i);
string propName = pi.Name;
【讨论】:
以上是关于如何通过反射获取当前属性名称?的主要内容,如果未能解决你的问题,请参考以下文章