使用属性名称调用属性或方法

时间:2010-09-14 03:59:26

标签: c# reflection methods properties attributes

假设我有一个看起来像这样的课程:

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

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

如何使用CodeName而不是属性或方法名称调用这两个属性或方法?

2 个答案:

答案 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");
    }
}
}