通过CustomAttribute获取方法,然后调用

时间:2015-05-29 13:07:25

标签: c#

随着自定义属性和反射的大量学习曲线,我似乎仍然在苦苦挣扎。任何人都可以帮我解决这个问题吗?

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

这是装饰方法的CustomAttribute(它只是一个方法): 的 [ControllerName(名称="博客&#34)]

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 =="博客"
  • 获取属性
  • 按属性获取方法并调用

我不想按方法名称获取方法。

此致

2 个答案:

答案 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" } - 参数数组。

答案 1 :(得分: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进行检查,但我希望保持foreach周期简单和线性,并显示应该完成的所有其他检查。