2010-07-14 2 views
2

Учитывая строку с тем же именем поля объекта, как я могу получить ссылку на поле объекта?Доступ к атрибутам с использованием строки

Например, я передаю строку с именем «field1» методу GetFieldByStr, и у объекта есть поле field field1, как я могу получить ссылку на объект field1? Я предполагаю, что использую отражение как-то.

class Example { 
    private FieldExample attr1; 

    void GetFieldByStr(String str) { 
     // We get passed in "field1" as a string, now I want 
     // to get the field1 attribute. 
    } 
} 
+0

attr1 - это поле, не являющееся атрибутом в вашем примере. – Lee

+0

Тогда как бы получить доступ к полю с помощью строки? – Steve

ответ

4

You need to use Reflection:

FieldInfo field = typeof(Example).GetField(str); 
object value = field.GetValue(this); 

(Для свойств, используйте PropertyInfo)

Обратите внимание, что value является объектом; для того, чтобы сделать что-нибудь полезное с ним, вам нужно отдать его на какой-то класс или интерфейс (или использовать dynamic в C# 4).

2

Вы можете сделать это с Reflection library (либо FieldInfo или PropertyInfo в зависимости, если вы хотите, поле или свойство)

Пример:

void GetAttributesByStr(String str) { 
    FieldInfo attributeInfo = this.GetType().GetField(str); // you might want to use some Binding flags here like BindingFlags.Instance and BindingFlags.Public 

    attributeInfo.GetValue(this); // assign this to something or return it as an object 
} 
2

Вот идея, которая не зависит на отражение. Недостатком является то, что он требует некоторой настройки. Вы могли бы даже определить некоторые пользовательские атрибуты и использовать какой-нибудь умный код для автоматической установки при запуске приложения.

interface IAttributeStore 
{ 
    T GetAttribute<T>(string key); 
} 

class Example : IAttributeStore 
{ 
    public int ExampleID { get; set; } 

    public string FirstName { get; set; } 

    public string LastName { get; set; } 

    static Dictionary<string, Delegate> _AttributeAccessors; 

    static Example() 
    { 
     _AttributeAccessors = new Dictionary<string, Delegate>(); 

     _AttributeAccessors.Add("ExampleID", new Func<Example, int>((example) => example.ExampleID)); 
     _AttributeAccessors.Add("FirstName", new Func<Example, string>((example) => example.FirstName)); 
     _AttributeAccessors.Add("LastName", new Func<Example, string>((example) => example.LastName)); 
    } 

    #region IAttributeStore Members 

    public T GetAttribute<T>(string key) 
    { 
     Delegate accessor; 
     if (_AttributeAccessors.TryGetValue(key, out accessor)) 
     { 
      Func<Example, T> func = accessor as Func<Example, T>; 
      if (func != null) 
       return func(this); 
      else 
       throw new Exception(string.Format("The attribute with the given key \"{0}\" is not of type [{1}].", key, typeof(T).FullName)); 
     } 
     else 
     { 
      throw new ArgumentException(string.Format("No attribute exists with the given key: \"{0}\".", key), "key"); 
     } 
    } 

    #endregion 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     Example example = new Example() { ExampleID = 12345, FirstName = "Funky", LastName = "Town" }; 

     Console.WriteLine(example.GetAttribute<int>("ExampleID")); 
     Console.WriteLine(example.GetAttribute<string>("FirstName")); 
     Console.WriteLine(example.GetAttribute<string>("LastName")); 
    } 
} 

Update: Это казалось мне интересно, так что я бросил вместе альтернативную реализацию, которая использует атрибуты и методы расширения вместо интерфейса. Самое приятное в этом состоит в том, что для класса требуется очень мало кода (вам просто нужно добавить атрибуты), а код, который устанавливает делегаты, выполняется только в том случае, если приложение действительно запрашивает атрибут из определенного класса.

Я должен отдать должное ответу Марка Гравелла на this question за то, как динамически создавать делегат для получения свойства, заданного объектом PropertyInfo.

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, AllowMultiple = false, Inherited = true)] 
class AttributeStoreAttribute : Attribute 
{ 
} 

[AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = true)] 
class StoredAttributeAttribute : Attribute 
{ 
    public string Key { get; set; } 
} 

public static class AttributeStore<T> 
{ 
    static Dictionary<string, Delegate> _AttributeAccessors; 

    public static void Initialize() 
    { 
     _AttributeAccessors = new Dictionary<string, Delegate>(); 

     Type type = typeof(T); 

     // let's keep it simple and just do properties for now 
     foreach (var property in type.GetProperties()) 
     { 
      var attributes = property.GetCustomAttributes(typeof(StoredAttributeAttribute), true); 
      if (attributes != null && attributes.Length > 0) 
      { 
       foreach (object objAttribute in attributes) 
       { 
        StoredAttributeAttribute attribute = objAttribute as StoredAttributeAttribute; 
        if (attribute != null) 
        { 
         string key = attribute.Key; 

         // use the property name by default 
         if (string.IsNullOrEmpty(key)) 
          key = property.Name; 

         if (_AttributeAccessors.ContainsKey(key)) 
          throw new Exception(string.Format("An attribute accessor has already been defined for the given key \"{0}\".", key)); 

         Type typeOfFunc = typeof(Func<,>).MakeGenericType(type, property.PropertyType); 
         Delegate accessor = Delegate.CreateDelegate(typeOfFunc, null, property.GetGetMethod()); 
         _AttributeAccessors.Add(key, accessor); 
        } 
       } 
      } 
     } 
    } 

    public static object GetAttribute(T store, string key) 
    { 
     if (_AttributeAccessors == null) 
      Initialize(); 

     Delegate accessor; 
     if (_AttributeAccessors.TryGetValue(key, out accessor)) 
     { 
      return accessor.DynamicInvoke(store); 
     } 
     else 
     { 
      throw new ArgumentException(string.Format("No attribute exists with the given key: \"{0}\" on attribute store [{1}].", key, typeof(T).FullName), "key"); 
     } 
    } 

    public static TResult GetAttribute<TResult>(T store, string key) 
    { 
     if (_AttributeAccessors == null) 
      Initialize(); 

     Delegate accessor; 
     if (_AttributeAccessors.TryGetValue(key, out accessor)) 
     { 
      Func<T, TResult> func = accessor as Func<T, TResult>; 
      if (func != null) 
       return func(store); 
      else 
       throw new Exception(string.Format("The attribute with the given key \"{0}\" on attribute store [{1}] is not of type [{2}].", key, typeof(T).FullName, typeof(TResult).FullName)); 
     } 
     else 
     { 
      throw new ArgumentException(string.Format("No attribute exists with the given key: \"{0}\" on attribute store [{1}].", key, typeof(T).FullName), "key"); 
     } 
    } 
} 

public static class AttributeStoreExtensions 
{ 
    public static object GetAttribute<T>(this T store, string key) 
    { 
     return AttributeStore<T>.GetAttribute(store, key); 
    } 

    public static TResult GetAttribute<T, TResult>(this T store, string key) 
    { 
     return AttributeStore<T>.GetAttribute<TResult>(store, key); 
    } 
} 

[AttributeStore] 
class Example 
{ 
    [StoredAttribute] 
    public int ExampleID { get; set; } 

    [StoredAttribute] 
    public string FirstName { get; set; } 

    [StoredAttribute] 
    public string LastName { get; set; } 
} 

[AttributeStore] 
class Example2 
{ 
    [StoredAttribute] 
    [StoredAttribute(Key = "ID")] 
    public int ExampleID { get; set; } 

    [StoredAttribute] 
    [StoredAttribute(Key = "First")] 
    public string FirstName { get; set; } 

    [StoredAttribute] 
    [StoredAttribute(Key = "Last")] 
    public string LastName { get; set; } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     Example example = new Example() { ExampleID = 12345, FirstName = "Funky", LastName = "Town" }; 

     Console.WriteLine(example.GetAttribute("ExampleID")); 
     Console.WriteLine(example.GetAttribute("FirstName")); 
     Console.WriteLine(example.GetAttribute("LastName")); 

     Example2 example2 = new Example2() { ExampleID = 12345, FirstName = "Funky", LastName = "Town" }; 

     // access attributes by the default key (property name) 
     Console.WriteLine(example2.GetAttribute("ExampleID")); 
     Console.WriteLine(example2.GetAttribute("FirstName")); 
     Console.WriteLine(example2.GetAttribute("LastName")); 

     // access attributes by the explicitly specified key 
     Console.WriteLine(example2.GetAttribute("ID")); 
     Console.WriteLine(example2.GetAttribute("First")); 
     Console.WriteLine(example2.GetAttribute("Last")); 
    } 
} 
+1

Проголосовали за подробный ответ, а потому, что вы ответили «666», – Steve

0

Для недвижимости.

var prop = this.GetType().GetProperty(str); 
prop.GetValue(prop, null); 
Смежные вопросы