假设我有一个看起来像这样的课程:
public class CallByAttribute
{
[CodeName("Foo")]
public string MyProperty { get; set; }
[CodeName("Bar")]
public string MyMethod(int someParameter)
{
return myDictionary[someParameter];
}
}
如何使用CodeName而不是属性或方法名称调用这两个属性或方法?
答案 0 :(得分: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();
答案 1 :(得分: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");
}
}
}