2012-12-21 29 views
2

我需要訪問類似strClassname.strPropertyName我將在程序執行中爲strClassnamestrProperty名稱使用不同的值。動態訪問類及其在C#中的屬性

請直接指導我。

+2

你能解釋一下嗎?名稱如何變化?你怎麼知道哪個類名和哪個屬性找到?他們是參數嗎? –

+1

你需要谷歌的「反思C#」 - 看看你是否可以弄明白,或再次問一個更具體的問題。 – Blorgbeard

+0

你可能會讓你的程序更加複雜,因爲通常會有一些更簡單的替代方法,而不需要「動態訪問類字段」。 –

回答

3

您可以使用反射:

要獲得屬性的名稱爲特定類型的使用方法Type.GetProperties。方法返回PropertyInfo對象的數組,通過PropertyInfo.Name屬性可以使用屬性名稱。如果您只想獲取所有屬性的子集(例如,只有公共靜態屬性),則在調用GetProperties方法時使用BindingFlags。您必須指定至少兩個標誌,一個來自Public/NonPublic,一個來自實例/靜態標誌。如果使用不帶BindingFlags參數的GetProperties,則默認標誌爲Public + NonPublic + Instance。

以下示例顯示如何獲取公共靜態屬性。

using System.Reflection; // reflection namespace 

// get all public static properties of MyClass type 
PropertyInfo[] propertyInfos; 
propertyInfos = typeof(MyClass).GetProperties(BindingFlags.Public | 
               BindingFlags.Static); 
// sort properties by name 
Array.Sort(propertyInfos, 
     delegate(PropertyInfo propertyInfo1, PropertyInfo propertyInfo2) 
     { return propertyInfo1.Name.CompareTo(propertyInfo2.Name); }); 

// write property names 
foreach (PropertyInfo propertyInfo in propertyInfos) 
{ 
    Console.WriteLine(propertyInfo.Name); 
} 

[Source]

0

如果有一百個左右的類別,你知道你要訪問的每一個特定的屬性,你知道每一個類將被實例化,你應該絕對考慮創建一個界面持有你想訪問的財產前。

public interface INamed 
{ 
    Name { get; } 
} 

用法示例:

var namedInstances = listOfClasses.Of<INamed>().Cast<INamed>(); 

foreach(var instance in namedInstances) 
{ 
    var name = instance.Name; 
} 

在另一方面,如果你不打算將這些類別實例,你可以試試下面的辦法,而不是當「名稱」屬性是靜態或const :

public interface INamed { } //Marker interface 

public static class GetNamedHelper 
{ 
    private static IEnumerable<Type> GetAssemblyTypes(IEnumerable<Assembly> assemblies) 
    { 
     if (assemblies == null) yield break; 

     foreach (var assembly in assemblies.Where(assembly => assembly != null)) 
     { 
      IEnumerable<Type> types; 
      try 
      { 
       types = assembly.GetTypes().Where(t => t != null); 
      } 
      catch (ReflectionTypeLoadException rtle) 
      { 
       types = rtle.Types.Where(t => t != null); 
      } 
      foreach (var type in types) 
       yield return type; 
     } 
    } 

    private static readonly Type namedMarkerInterface = typeof (INamed); 

    public static IEnumerable<string> GetNames(params Assembly[] assemblies) 
    { 
     var types = GetAssemblyTypes(assemblies) 
      .Where(t => t.GetInterfaces().Any(intf => intf == namedMarkerInterface)); 

     foreach (var type in types) 
     { 
      //ex. public static string Name 
      var prop = type.GetProperty("Name", BindingFlags.Public | BindingFlags.Static); 
      if (prop == null || !prop.CanRead) continue; 
      yield return prop.GetValue(null, null) as string; 

      //ex. public const string Name 
      var field = type.GetField("Name", BindingFlags.Public); 
      if (field == null || !field.IsStatic) continue; 
      yield return field.GetValue(null) as string; 
     } 
    } 
} 

無論如何,你需要知道要檢查哪些類和什麼。

3

聽起來像你想要在運行時獲取(或設置)對象的屬性值。因此,這裏的最基本的方式做到這一點:

public static object GetPropertyValue(object instance, string strPropertyName) 
{ 
    Type type = instance.GetType(); 
    System.Reflection.PropertyInfo propertyInfo = type.GetProperty(strPropertyName); 
    return propertyInfo.GetValue(instance, null); 
} 

...並設置值:

public static void SetPropertyValue(object instance, string strPropertyName, object newValue) 
{ 
    Type type = instance.GetType(); 
    System.Reflection.PropertyInfo propertyInfo = type.GetProperty(strPropertyName); 
    propertyInfo.SetValue(instance, newValue, null); 
} 

如果你正在試圖獲得一個類的屬性的名稱,這裏有一個該函數:

public static IEnumerable<string> GetPropertyNames(string className) 
{ 
    Type type = Type.GetType(className); 
    return type.GetProperties().Select(p => p.Name); 
} 

說,你有100個對象,並希望得到他們每個人的名稱屬性的值,這裏是一個將做一個函數:

public static IEnumerable<String> GetNames(IEnumerable<Object> objects, string nameProperty = "Name") 
{ 
    foreach (var instance in objects) 
    { 
     var type = instance.GetType(); 
     var property = type.GetProperty(nameProperty); 
     yield return property.GetValue(instance, null) as string; 
    } 
}