2009-12-02 26 views
0

可能重複:
Finding the Variable Name passed to a Function in C#如何將變量名稱轉換爲c#.net中的字符串?

public new Dictionary<string, string> Attributes { get; set; } 
public string StringAttributes = string.Empty; 

public int? MaxLength { get; set; } 
public int? Size { get; set; } 
public int? Width { get; set; } 
public int? Height { get; set; } 

protected override void OnInit(EventArgs e) { 
    Attributes = new Dictionary<string, string>(); 
    Attributes.Add("MaxLength", MaxLength.ToString()); 
    Attributes.Add("Size", Size.ToString()); 
    Attributes.Add("Width", Width.ToString()); 
    Attributes.Add("Height", Height.ToString()); 
    base.OnInit(e); 
} 

protected override void OnPreRender(EventArgs e) { 
    if (Attributes != null) { 
     StringBuilder attributes = new StringBuilder(); 
     foreach (var item in Attributes) { 
      if (!string.IsNullOrWhiteSpace(item.Value)) { 
       attributes.Append(item.Key + "=\"" + item.Value + "\" "); 
      } 
     } 
     StringAttributes = attributes.ToString(); 
    } 
} 

這裏的問題是,而是採用Attributes.Add("MaxLength", MaxLength.ToString());重複其他性質相同的過程,可能我們不只是做一個函數,還能夠爲字典添加值,其中要添加的鍵是它們的變量名稱? 說,

public void addAttribute(object variable){ 
    Attributes = new Dictionary<string, string>(); 
    Attributes.Add(variable.Name, variable.Value); 
}... 

我想這也是可以做到與反思,讓所有的空的屬性,並通過然後將它們添加到每個字典循環......但只要有任何其他的方式,我們不會堅持反思。

但如果反射是唯一的選擇,那麼另一個問題現在是如何獲取類的空的屬性...

任何幫助將不勝感激。謝謝。

+1

看一看:

Dictionary<string, string> attributes = Inspector<MyClass>.Inspect(target); 

在我的示例代碼中的反射,因爲它是我的通用檢查類的靜態構造函數中執行的每種類型的檢查執行一次, http://stackoverflow.com/questions/72121/finding-the-variable-name-passed-to-a-function-in-c – adrianbanks 2009-12-02 23:34:52

+0

我不知道我們可以使用這個表達式... '公共字符串GetPropertyName(表達式>變量){ return(variable.Body as MemberExpression).Member.Name; }' – Jronny 2009-12-03 03:43:05

+0

是的,這個問題在這裏不止一次被問到。這裏是一個更多的鏈接:http://stackoverflow.com/questions/1669016/how-do-you-get-a-c-property-name-as-a-string-with-reflection – 2009-12-03 19:09:49

回答

3

我想不出沒有反射的方法。

爲了讓所有空的屬性你可以在你類似的代碼如下:

GetType().GetProperties() 
     .Where(property => 
      property.PropertyType.IsGenericType && 
      property.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>)) 

填充屬性字典使用例如:

PropertyInfo[] typeProperties = GetType().GetProperties(); 
var nullableProperties = typeProperties.Where(property => 
    property.PropertyType.IsGenericType && 
    property.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>)); 

var attributes = new Dictionary<string, string>(); 
foreach (var nullableProperty in nullableProperties) 
{ 
    object value = nullableProperty.GetValue(this,null); 
    attributes.Add(nullableProperty.Name, value == null ? 
               string.Empty : value.ToString()); 
} 
+0

謝謝...但我現在的問題是如何得到值 foreach(var屬性typeProperties){ Attributes.Add(item.Name,item。*無法在這裏獲得值*); } – Jronny 2009-12-02 19:25:37

+0

將用法示例替換爲填充字典中屬性的類似內容:) – Elisha 2009-12-02 19:28:50

+0

謝謝。我稍後再試一試。 – Jronny 2009-12-02 19:58:43

2

我不知道我完全理解你沒有更多上下文的問題,但也許這是有幫助的

如果擔心超過多個調用的反射開銷:

如果問題越來越通過強類型編譯一個變量名,那麼你可以使用

我看到會員類來自Oliver Hhanappi的帖子。它的使用示例在這裏我的blog

+0

有一天我可能需要使用它。 – Jronny 2009-12-03 06:30:54

+0

這是哪一個?我給了4個可能的解決方案/想法 – Maslow 2009-12-03 13:42:21

+0

信息緩存...但其他人也可能有用的一天。謝謝。 – Jronny 2009-12-04 02:39:39

1

您可以使用以下函數從類中提取公共Nullable屬性到您要查找的格式。它也爲該值調用getter方法。

這與@Elisha談到的使用相同的反射用法。它還會對getter返回的值進行.ToString()調用。

IDictionary<string, string> GetProps<T>(T DataObject) 
{ 
    if(null == DataObject) 
     return new Dictionary<string, string>(); 
    var nullableProperties = 
     from property in typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public) 
     from accessor in property.GetAccessors(false) 
     let returnType = accessor.ReturnType 
     where returnType.IsGenericType 
     && returnType.GetGenericTypeDefinition() == typeof(Nullable<>) 
     && accessor.GetParameters().Length == 0 
     select new { Name=property.Name, Getter=accessor}; 
    return nullableProperties.ToDictionary(
     x => x.Name, 
     x => x.Getter.Invoke(DataObject, null).ToString()); 
} 
1

下面是我的完整解決方案。我會說你最好的選擇就是使用反思,因爲你所要求的是一種元任務。至於如何知道要添加哪些屬性,我會建議定義自己的屬性並將其應用於要檢查的字段/屬性。

用法:

// apply this attribute to any properties or fields that you want added to the attributes dictionary 
[AttributeUsage(
    AttributeTargets.Property | 
    AttributeTargets.Field | 
    AttributeTargets.Class | 
    AttributeTargets.Struct | 
    AttributeTargets.Interface, 
    AllowMultiple = true, Inherited = true)] 
public class InspectAttribute : Attribute 
{ 
    // optionally specify the member name explicitly, for use on classes, structs, and interfaces 
    public string MemberName { get; set; } 

    public InspectAttribute() { } 

    public InspectAttribute(string memberName) 
    { 
     this.MemberName = memberName; 
    } 
} 

public class Inspector<T> 
{ 
    // Inspector is a generic class, therefore there will be a separate instance of the _InspectActions variable per type 
    private static List<Action<Dictionary<string, string>, T>> _InspectActions; 

    static Inspector() 
    { 
     _InspectActions = new List<Action<Dictionary<string, string>, T>>(); 
     foreach (MemberInfo m in GetInspectableMembers(typeof(T))) 
     { 
      switch (m.MemberType) 
      { 
       case MemberTypes.Property: 
        { 
         // declare a separate variable for variable scope with anonymous delegate 
         PropertyInfo member = m as PropertyInfo; 
         // create an action delegate to add an entry to the attributes dictionary using the property name and value 
         _InspectActions.Add(
          delegate(Dictionary<string, string> attributes, T item) 
          { 
           object value = member.GetValue(item, null); 
           attributes.Add(member.Name, (value == null) ? "[null]" : value.ToString()); 
          }); 
        } 
        break; 
       case MemberTypes.Field: 
        { 
         // declare a separate variable for variable scope with anonymous delegate 
         FieldInfo member = m as FieldInfo; 
         // need to create a separate variable so that delegates do not share the same variable 
         // create an action delegate to add an entry to the attributes dictionary using the field name and value 
         _InspectActions.Add(
          delegate(Dictionary<string, string> attributes, T item) 
          { 
           object value = member.GetValue(item); 
           attributes.Add(member.Name, (value == null) ? "[null]" : value.ToString()); 
          }); 
        } 
        break; 
       default: 
        // for all other member types, do nothing 
        break; 
      } 
     } 
    } 

    private static IEnumerable<MemberInfo> GetInspectableMembers(Type t) 
    { 
     // get all instance fields and properties 
     foreach (MemberInfo member in t.GetMembers(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy | BindingFlags.GetField | BindingFlags.GetProperty)) 
     { 
      // check if the current member is decorated with an Inspect attribute 
      object[] inspectAttributes = member.GetCustomAttributes(typeof(InspectAttribute), true); 
      if (inspectAttributes != null && inspectAttributes.Length > 0) 
      { 
       yield return member; 
      } 
     } 

     // now look for any Inspect attributes defined at the type level 
     InspectAttribute[] typeLevelInspectAttributes = (InspectAttribute[])t.GetCustomAttributes(typeof(InspectAttribute), true); 
     if (typeLevelInspectAttributes != null && typeLevelInspectAttributes.Length > 0) 
     { 
      foreach (InspectAttribute attribute in typeLevelInspectAttributes) 
      { 
       // search for members matching the name provided by the Inspect attribute 
       MemberInfo[] members = t.GetMember(attribute.MemberName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetField | BindingFlags.GetProperty | BindingFlags.FlattenHierarchy); 

       if (members != null && members.Length > 0) 
       { 
        foreach (MemberInfo member in members) 
        { 
         yield return member; 
        } 
       } 
      } 
     } 
    } 

    public static Dictionary<string, string> Inspect(T item) 
    { 
     // create a new attributes dictionary 
     Dictionary<string, string> attributes = new Dictionary<string, string>(); 
     foreach (Action<Dictionary<string, string>, T> inspectAction in _InspectActions) 
     { 
      // execute each "inspect" action. 
      // This will execute the delegates we created earlier, causing entries to be added to the dictionary 
      inspectAction(attributes, item); 
     } 
     return attributes; 
    } 
} 

public class BasePage 
{ 
    public int? SomeValue { get; set; } 
} 

// example class with properties decorated with the Inspect attribute 
[Inspect("SomeValue")] // also inspect the "SomeValue" property from the BasePage class 
public class MyPage : BasePage 
{ 
    [Inspect] 
    public int? MaxLength { get; set; } 
    [Inspect] 
    public int? Size { get; set; } 
    [Inspect] 
    public int? Width { get; set; } 
    [Inspect] 
    public int? Height { get; set; } 

    public string GenerateAttributeString() 
    { 
     System.Text.StringBuilder attributes = new System.Text.StringBuilder(); 
     foreach (KeyValuePair<string, string> item in Inspector<MyPage>.Inspect(this)) 
     { 
      attributes.Append(item.Key + "=\"" + item.Value + "\" "); 
     } 
     return attributes.ToString(); 
    } 
} 
相關問題