2010-09-14 70 views
4

比方說,我有一個類,看起來像這樣:調用屬性或使用屬性的方法名

public class CallByAttribute 
{ 
    [CodeName("Foo")] 
    public string MyProperty { get; set; } 

    [CodeName("Bar")] 
    public string MyMethod(int someParameter) 
    { 
     return myDictionary[someParameter]; 
    } 
} 

我怎麼會叫這兩個屬性或方法,使用替代屬性或方法名稱代號?

回答

5

方法1:

public static TOutput GetPropertyByCodeName<TOutput>(this object obj, string codeName) 
{ 
    var property = obj.GetType() 
         .GetProperties() 
         .Where(p => p.IsDefined(typeof(CodeNameAttribute), false)) 
         .Single(p => ((CodeNameAttribute)(p.GetCustomAttributes(typeof(CodeNameAttribute), false).First())).Name == codeName); 

    return (TOutput)property.GetValue(obj, null); 
} 

注:如果沒有屬性與存在,這將拋出指定codeName或者多個屬性共享相同的codeName

用法:

CallByAttribute obj= ... 
string myProperty = obj.GetPropertyByCodeName<string>("Foo"); 

方法2:

如果你是C#4,你可以編寫自己的System.Dynamic.DynamicObject可路由動態調用正確的成員。

這將允許更清晰的語法。例如,你應該能夠有所作爲,使:

CallByAttribute obj= ... 
dynamic objectByCodeName = new ObjectByCodeName(obj); 
objectByCodeName.Foo = "8"; 
objectByCodeName.Bar(); 
+0

看起來你需要'CodeName'的一個伴侶'Attribute'類;這是真的,還是你可以只反映一下屬性來獲取每個的CodeName? – 2010-09-14 04:11:07

+2

Robert:假設你已經有了一個'CodeNameAttribute'類,否則你將無法執行'[CodeName(「foo」)]',因爲這實際上導致了一個'CodeNameAttribute'對象的實例化。 – Gabe 2010-09-14 04:13:30

+1

如果您打算使用這些代碼名(數千次或數百萬次),您需要將屬性查找的結果緩存爲可在字典中查找的代理。 – Gabe 2010-09-14 05:47:29

3

下面是一些完全工作的代碼,包括可選調用參數:

private static string Call(object callByAttribute, string name, object[] args) 
    { 
     PropertyInfo prop = callByAttribute.GetType().GetProperties() 
      .Where(p => p.IsDefined(typeof(CodeNameAttribute), false)) 
      .SingleOrDefault(p => ((CodeNameAttribute)(p.GetCustomAttributes(typeof(CodeNameAttribute), false)).First()).Name == name); 
     if (prop != null) 
      return (string)callByAttribute.GetType().InvokeMember(prop.Name, BindingFlags.GetProperty, null, callByAttribute, null); 


     MethodInfo method = callByAttribute.GetType().GetMethods() 
      .Where(p => p.IsDefined(typeof(CodeNameAttribute), false)) 
      .SingleOrDefault(p => ((CodeNameAttribute)(p.GetCustomAttributes(typeof(CodeNameAttribute), false)).First()).Name == name); 
     if (method != null) 
      return (string)callByAttribute.GetType().InvokeMember(method.Name, BindingFlags.InvokeMethod, null, callByAttribute, args); 

     throw new Exception("method/getter not found"); 
    } 
    private static string Call(object callByAttribute, string name) 
    { 
     return Call(callByAttribute, name, null); 
    } 

這可以在一個完整的程序中使用這樣的:

using System; 
using System.Linq; 
using System.Reflection; 

namespace ConsoleApplication1 
{ 
public class CallByAttribute 
{ 
    [CodeName("Foo")] 
    public string MyProperty { get; set; } 

    [CodeName("Bar")] 
    public string MyMethod(int someParameter) 
    { 
     return "blah" + someParameter; 
    } 
} 

public class CodeNameAttribute : Attribute 
{ 
    private readonly string name; 

    public CodeNameAttribute(string name) 
    { 
     this.name = name; 
    } 

    public string Name 
    { 
     get { return name; } 
    } 
} 


class Program 
{ 
    static void Main(string[] args) 
    { 
     CallByAttribute callByAttribute = new CallByAttribute(); 
     callByAttribute.MyProperty = "hi"; 

     Console.WriteLine(Call(callByAttribute, "Bar", new object[] {1})); 
     Console.WriteLine(Call(callByAttribute, "Foo")); 

    } 
    private static string Call(object callByAttribute, string name) 
    { 
     return Call(callByAttribute, name, null); 
    } 


    private static string Call(object callByAttribute, string name, object[] args) 
    { 
     PropertyInfo prop = callByAttribute.GetType().GetProperties() 
      .Where(p => p.IsDefined(typeof(CodeNameAttribute), false)) 
      .SingleOrDefault(p => ((CodeNameAttribute)(p.GetCustomAttributes(typeof(CodeNameAttribute), false)).First()).Name == name); 
     if (prop != null) 
      return (string)callByAttribute.GetType().InvokeMember(prop.Name, BindingFlags.GetProperty, null, callByAttribute, null); 

     MethodInfo method = callByAttribute.GetType().GetMethods() 
      .Where(p => p.IsDefined(typeof(CodeNameAttribute), false)) 
      .SingleOrDefault(p => ((CodeNameAttribute)(p.GetCustomAttributes(typeof(CodeNameAttribute), false)).First()).Name == name); 
     if (method != null) 
      return (string)callByAttribute.GetType().InvokeMember(method.Name, BindingFlags.InvokeMethod, null, callByAttribute, args); 

     throw new Exception("method/getter not found"); 
    } 
} 
}