我正在学习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参数进行重载 - 如果失败,则没有任何参数的重载
答案 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;你正在定义的。