2015-05-29 37 views
0

随着自定义属性和反射的大量学习曲线,我似乎仍在挣扎。任何人都可以帮我解决这个问题吗?通过CustomAttribute获取方法,然后调用

基本上我想调用一个基于它的属性的方法。

这是装饰方法的CustomAttribute(它将永远只能是一个方法): [ControllerName(NAME = “博客”)

public static string GetContent(string controllerName, string singleItemName = "") 
{ 
    string returnVal = null; 
    //Get the class type 
    Type thisType = typeof(ContentFacade); 

    //Get member info 
    System.Reflection.MemberInfo info = typeof(ContentFacade); 

    Loop through attributes 
    foreach (object attrib in info.GetCustomAttributes(true)) 
    { 
     //if the attribute matches the param controller name 
     //then invoke 
     if (attrib == controllerName) 
     { 
      //Get the method by attribute not method name 
      //I dont want to get the method by MethodName 
      MethodInfo theMethod = thisType.GetMethod(controllerName); 

      //Return the value as it will be html for the end user 
      returnVal = (string)theMethod.Invoke(controllerName, null); 
     } 
    } 

    return returnVal; 
} 

同样,如果可能的话,我想通过属性获取方法。

真的很期待在这方面得到一些帮助。

///编辑 对不起,我在代码中添加了注释来说明问题。 基本上我想:

  • 找controllerName属性==“博客”
  • 通过属性获取方法和调用

我不想获得由法方法名称。

问候,

+1

你有什么实际问题? –

+0

我确实认为你的问题比“方法的名称是什么”更符合逻辑。想一想你想做什么,一切都会变得简单。你发布的代码似乎有逻辑问题。 – xanatos

+0

@xanatos好诡秘的评论:)精心制作? –

回答

1

一个简单的例子是:

public static string GetContent(Type type, string controllerName) 
{ 
    foreach (MethodInfo method in type.GetMethods(BindingFlags.Static | BindingFlags.Public)) 
    { 
     ControllerNameAttribute controller = (ControllerNameAttribute)method.GetCustomAttribute(typeof(ControllerNameAttribute)); 

     if (controller == null) 
     { 
      continue; 
     } 

     if (controller.Name != controllerName) 
     { 
      continue; 
     } 

     if (method.IsGenericMethod) 
     { 
      throw new InvalidOperationException(); 
     } 

     if (method.GetParameters().Length != 0) 
     { 
      throw new InvalidOperationException(); 
     } 

     if (method.ReturnType != typeof(string)) 
     { 
      throw new InvalidOperationException(); 
     } 

     string result = (string)method.Invoke(null, null); 
     return result; 
    } 

    throw new InvalidOperationException(); 
} 

您可以使用它喜欢:

string result = GetContent(typeof(Program), "blog"); 

哪里Program是其中的方法应该是一流的。

请注意,正如所写,此代码仅适用于static方法。如果你想使用实例方法,将其更改为:

public static string GetContent(object instance, string controllerName) 
{ 
    Type type = instance.GetType(); 

    foreach (MethodInfo method in type.GetMethods(BindingFlags.Static | BindingFlags.Public)) 
    { 
     ControllerNameAttribute controller = (ControllerNameAttribute)method.GetCustomAttribute(typeof(ControllerNameAttribute)); 

     if (controller == null) 
     { 
      continue; 
     } 

     if (controller.Name != controllerName) 
     { 
      continue; 
     } 

     if (method.IsGenericMethod) 
     { 
      throw new InvalidOperationException(); 
     } 

     if (method.GetParameters().Length != 0) 
     { 
      throw new InvalidOperationException(); 
     } 

     if (method.ReturnType != typeof(string)) 
     { 
      throw new InvalidOperationException(); 
     } 

     string result = (string)method.Invoke(instance, null); 
     return result; 
    } 

    throw new InvalidOperationException(); 
} 

一般情况下,这两种方法不检查是否存在给定controllerName一个方法。他们只是执行找到的第一个。甚至可以执行检查,通常使用LINQ,但我想保持简单和线性的循环,并显示应该完成的所有其他检查。

+0

是否有任何理由在方法体中添加“Type”作为参数,而不是在方法体中声明?还有什么目的(循环外):抛出新的InvalidOperationException(); ?遗留代码? –

+0

@TezWingfield你不清楚你是否有一个包含所有方法的类,或者是否有多个类可以以某种方式“选择”,或者使用的类是否依赖于代码的“区域”是。抛出新的InvalidOperationException();'将会完成,如果你做了错误的编码。例如,如果标记的方法没有正确的签名,或者如果没有有效的方法(最后一个,在'foreach'之外)。 – xanatos

+0

我重新研究了上述解决方案,并从中学习并获得了自己的版本。由于列入了“抛出异常”,我将其标记为回答。伟大的工作谢谢你。 –

1

代码示例

public class MyClass 
{ 
    [System.ComponentModel.DisplayName("my test method")] 
    public bool TestMethod(string input) 
    { 
     return input == "OK"; 
    } 

    [System.ComponentModel.DisplayName("my second method")] 
    public string TestMethod2(string input) 
    { 
     return input; 
    } 

    public void Invoke(string displayName) 
    { 
     // attribute type we search 
     Type attributeType = typeof(System.ComponentModel.DisplayNameAttribute); 

     // find method 
     var methodInfo = (from e in this.GetType().GetMethods() 
          let attributes = e.GetCustomAttributes(attributeType).Cast<System.ComponentModel.DisplayNameAttribute>().ToArray() 
          where attributes.Length != 0 && 
           attributes.Any(x => string.Equals(x.DisplayName, displayName, StringComparison.InvariantCultureIgnoreCase)) 
          select e).FirstOrDefault(); 

     if (methodInfo != null) 
     { 
      // method found 
      Console.WriteLine("Invoke {0} method: {1}", methodInfo.Name, methodInfo.Invoke(this, new object[] { "OK" })); 
     } 
    } 
} 

评论

  1. this.GetType().GetMethods() - 让所有的方法,你可以指定哪一种方法,你想BindingFlags返回。
  2. e.GetCustomAttributes(typeof(System.ComponentModel.DisplayNameAttribute)) - 获取指定的类型
  3. methodInfo.Invoke(this, new object[] { "OK" })的所有属性 - 方法调用,this - 类实例(null静态方法),new object[] { "OK" } - 阵列的参数。
+0

虽然这应该工作,它是可怕的阅读。从OP张贴的循环更适合我猜。 – HimBromBeere

+0

我爱查询语法哈哈...只是在我答复答案之前查看两个答案并向他们学习。我从不喜欢“复制和粘贴”,更多首先理解。 –

相关问题