【问题标题】:Get a method with a single or no attributes with Reflection in C#在 C# 中使用反射获取具有单个或没有属性的方法
【发布时间】:2016-06-22 20:28:26
【问题描述】:

我正在学习反射,我正在研究一种可序列化的动作类型,它可以被保存,然后加载和触发。可序列化操作支持无参数或 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 参数的重载 - 如果失败,不带任何参数的重载

【问题讨论】:

  • 您可以改用GetMethods 并循环直到找到匹配项。不过,就我个人而言,如果我需要一种特定的方法,我会询问有助于找到正确方法的参数类型。

标签: c# system.reflection


【解决方案1】:

对于您的特定要求,在 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;

此时,您评估从查询中出来的方法,看看它们是否满足您的需求。

不过,还有一个不同的问题,那就是“应该我这样做吗?”。 TyCobb 已经在他的评论中提到了这一点,他是对的。

您当前尝试做事的方式是做大量工作却没有立竿见影的效果。所以你得到一个重载列表,这对你没有帮助。现在您必须自己进行重载解析并找到要调用的“最佳”重载(或者只使用您找到的第一个,但如果添加/删除/更改方法,这很容易中断)。

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

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

更简单、更清晰、更明显正确!您甚至不必在这里检查允许的参数类型,让它们作为构造您正在定义的有效“动作类型”的一部分进行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-16
    • 2014-12-31
    • 2011-10-13
    • 1970-01-01
    相关资源
    最近更新 更多