如何通过reflection获取当前的属性名称?

我想通过reflection机制获取属性名称。 可能吗?

更新:我有这样的代码:

public CarType Car { get { return (Wheel) this["Wheel"];} set { this["Wheel"] = value; } } 

而且因为我需要更多这样的属性,我想要做这样的事情:

  public CarType Car { get { return (Wheel) this[GetThisPropertyName()];} set { this[GetThisPropertyName()] = value; } } 

由于属性实际上只是方法,你可以做到这一点,并清理返回的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倍)。

这就是说,我相信性能问题不会引起太多的问题,尽pipe在这里可以find关于StackFrame慢度的有趣讨论。

如果您担心性能,我想另一种select是创build一个Visual Studio智能感知代码片段,为您创build属性并创build与属性名称对应的string。

我想知道更多关于您需要的上下文,因为在我看来,您应该已经知道您在属性访问器中正在使用哪个属性。 但是,如果您必须使用MethodBase.GetCurrentMethod(). Name并在get_/set_之后移除任何内容。

更新

根据你的改变,我会说你应该使用inheritance而不是reflection。 我不知道你的字典中有什么数据,但是在我看来,你真的想要有不同的汽车类,比如轿车,敞篷跑车,越野车,旅行车,不要把types保存在局部variables中。 那么你会有实现的方法,做适合这种types的车的事情。 而不是找出你有什么样的车,然后做一些事情,然后简单地调用适当的方法,Car对象根据它是什么types来做正确的事情。

  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... } } 

使用MethodBase.GetCurrentMethod()来代替!

reflection用于处理在编译时无法完成的types。 获取你所在的属性访问器的名字可以在编译时决定,所以你可能不应该使用reflection。

不过,您可以使用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_",""); } 

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的自定义属性类。

我强烈build议不要使用GetStackFrame()作为您的解决scheme的一部分,我的原始版本的解决scheme原本是更整洁:

 return GetPropValue<string>(); 

但是比上面的版本慢了600倍。

你提出的例子有点混乱,除非我不明白。 从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; } 

是的!

 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; } 

尝试使用System.Diagnostics.StackTrace来反映在调用堆栈上。 该属性应该在调用堆栈中的某个地方(如果您直接从属性代码中调用该属性,则可能位于顶部)。