Вызов свойства или метода с использованием имени атрибута - PullRequest
4 голосов
/ 14 сентября 2010

Допустим, у меня есть класс, который выглядит следующим образом:

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

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

Как бы я назвал эти два свойства или метода, используя CodeName вместо имени свойства или метода?

Ответы [ 2 ]

5 голосов
/ 14 сентября 2010

Метод 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();
3 голосов
/ 14 сентября 2010

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

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