簡體   English   中英

如何通過反射獲取當前屬性名稱?

[英]How to get current property name via 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倍)。

這就是說我確信性能問題不會引起太多問題 - 盡管可以在這里找到有關StackFrame慢度的有趣討論。

我想如果您擔心性能,另一個選擇是創建一個Visual Studio Intellisense代碼片段,為您創建屬性,並創建一個與屬性名稱對應的字符串。

我想知道更多關於你需要它的上下文,因為在我看來你應該已經知道你在屬性訪問器中使用了什么屬性。 但是,如果必須,可以使用MethodBase.GetCurrentMethod()。 Name並在get_/set_之后刪除任何內容。

更新

根據您的更改,我會說您應該使用繼承而不是反射。 我不知道你的詞典里有什么數據,但在我看來你真的想擁有不同的Car類,比如Sedan,Roadster,Buggy,StationWagon,不要把類型保存在局部變量中。 然后你會有方法的實現,為那種類型的汽車做正確的事情。 然后你可以簡單地調用適當的方法,而不是找出你擁有的汽車類型,然后根據它的類型做出合適的方法。

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

你提出的例子有點令人困惑,除非我沒有得到它。 從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;
}  

請改用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_","");
    }

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倍。

是的!

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來反映調用堆棧。 該屬性應該位於調用堆棧中的某個位置(如果您直接從屬性的代碼中調用它,則可能位於頂部)。

方式#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.CurrPropNameProps.CurrMethodName


方式#4

.NET 4.5+的解決方案:

public static class Props
{
    public static string GetCallerName([System.Runtime.CompilerServices.CallerMemberName] String propertyName = "")
    {
         return propertyName;
    }
}

usgae: Props.GetCallerName();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM