【问题标题】:Calling a property or method using an attribute name使用属性名称调用属性或方法
【发布时间】:2010-09-14 03:59:25
【问题描述】:

假设我有一个如下所示的类:

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

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

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

【问题讨论】:

    标签: c# reflection methods properties attributes


    【解决方案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");
    

    方法二:

    如果您使用的是 C# 4,则可以编写自己的 System.Dynamic.DynamicObject,将动态调用路由到正确的成员。

    这将允许更简洁的语法。例如,您应该能够完成一些允许:

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

    【讨论】:

    • 看来你需要一个 Attribute 的同伴 CodeName 类;是这样吗,还是您可以仅反映属性以获取每个属性的 CodeName?
    • 罗伯特:大概你已经有一个CodeNameAttribute 类,否则你将无法执行[CodeName("foo")],因为这实际上会导致CodeNameAttribute 对象的实例化。
    • 如果您要大量使用这些代号(数千或数百万次),您需要将属性查找的结果缓存为可以在字典中查找的委托。
    【解决方案2】:

    这是一些完整的工作代码,包括可选的调用参数:

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

    【讨论】:

      猜你喜欢
      • 2014-05-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-27
      • 2012-10-24
      • 1970-01-01
      相关资源
      最近更新 更多