使用C#中的Reflection获取具有单个属性或无属性的方法

时间:2016-06-22 20:28:27

标签: c# system.reflection

我正在学习Reflection,我正在研究一个可序列化的动作类型,可以保存然后加载和触发。 serializeable动作支持不带参数的方法或int,float,double,string或bool类型的单个参数。

传递名称的方法的所有都具有上面列出的类型的一个属性,或者根本没有没有属性还有一个具有默认值的属性。 这就是我的问题。首先,当我为一个有重载的方法调用target.GetType().GetMethod(methodName);时,我得到一个AmbiguousMatchException,如果我为一个带有单个可选参数的方法调用它,我会得到一个NULL。

所以我现在所做的就是从try-catch开始捕获AmbiguousMatchException,然后告诉我给定的方法有重载。如果我得到一个异常,我开始尝试让方法传递不同属性类型的数组来搜索:

public static MethodInfo GetMethod(string methodName, Object _target)
    {
        try
        {
            MethodInfo info = _target.GetType().GetMethod(methodName);
            return info;
        }
        catch (AmbiguousMatchException ex)
        {
            MethodInfo info = _target.GetType().GetMethod(methodName, new System.Type[0]);
            if (info != null) return info;
            info = _target.GetType().GetMethod(methodName, new[] { typeof(int) });
            if (info != null) return info;
            info = _target.GetType().GetMethod(methodName, new[] { typeof(float) });
            if (info != null) return info;
            info = _target.GetType().GetMethod(methodName, new[] { typeof(double) });
            if (info != null) return info;
            info = _target.GetType().GetMethod(methodName, new[] { typeof(string) });
            if (info != null) return info;
            info = _target.GetType().GetMethod(methodName, new[] { typeof(bool) });
            return info;
        }
    }

这非常难看,但它适用于重载方法。但是,如果方法具有可选参数,则返回NULL。我尝试使用OptionalParamBinding绑定标志,但即使对于没有重载和单个可选参数的方法,它也返回NULL。

所以我的问题是: 我该怎么办呢?我需要这个静态方法来查找:   - 带有int,float,double,string或bool参数的方法的重载   - 如果失败,则使用可选的int,float,double,string或bool参数进行重载   - 如果失败,则没有任何参数的重载

1 个答案:

答案 0 :(得分:3)

根据您的特定要求,在LINQ查询中执行此操作非常容易。

var validParameterTypes = new HashSet<Type> { typeof(int), typeof(float), ... };

var methods = from method in _target.GetType().GetMethods()
              let parameters = method.GetParameters()
              let hasParameters = parameters.Length > 0
              let firstParameter = hasParameters ? parameters[0] : null
              let isOptionalParameter = (hasParameters && firstParameter.IsOptional) ? true : false
              where method.Name == methodName &&
                    (!hasParameters || validParameterTypes.Contains(firstParameter.ParameterType))
              orderby parameters.Length descending, isOptionalParameter
              select method;

此时,您可以评估查询中出现的方法,看看它们是否符合您的需求。

但是,这是一个不同的问题,那就是&#34; 我应该这样做?&#34;。 TyCobb在他的评论中已经提到了这一点,他是对的。

目前你尝试做事的方式是很多工作,没有立即获益。所以你得到一个重载列表,这对你没什么帮助。现在你必须自己做重载决策并找到最好的&#34;调用过载(或者只是取你找到的第一个,但如果添加/删除/更改方法,这可能很容易破坏。)

我们假设您还存储了您要查找的参数类型(如果有)。知道这会将你的代码压缩到这个:

var parameterTypes = (knownParameterType == null ) ? Type.EmptyTypes : new[] { knownParameterType };
var method = _target.GetType().GetMethod(methodName, parameterTypes);

更简单,更清洁,更明显正确!你甚至不必在这里检查允许的参数类型,让他们这样做,作为构建有效的&#34;动作类型的一部分&#34;你正在定义的。