Во-первых, чтобы подчеркнуть возможность проблемы XY, я укажу, что моя основная цель - определить, содержит ли IInvocation определенный атрибут.
Для этого мне нужно получить MethodInfoпроизводного метода IInvocation.
Для этого мне нужно сравнить сигнатуру метода интерфейса IInvocation MethodInfo с сигнатурами всех методов в производном типе IInvocation.
Чтобы сделать это, Мне нужно проверить 'вид (значение, ссылку или вывод)' параметров .
Как?
Мой код (обратите внимание на TODO):
internal bool DoesInvocationContainAttribute<T>(IInvocation invocation) where T : Attribute
{
var request = invocation.Request;
var interfaceMethod = request.Method;
var interfaceType = interfaceMethod.DeclaringType;
var derivedType = request.Target.GetType();
var derivedMethod = GetDerivedMethod(derivedType, interfaceMethod);
return
derivedType.HasAttribute<T>()
|| (interfaceType?.HasAttribute<T>() ?? false)
|| derivedMethod.HasAttribute<T>()
|| interfaceMethod.HasAttribute<T>();
}
private static MethodInfo GetDerivedMethod(Type derivedType, MethodInfo interfaceMethod)
=> derivedType.GetMethods().Single(
derivedMethod => derivedMethod.Name == interfaceMethod.Name
&& AreParamsEqualForOverloadResolution(derivedMethod.GetParameters(), interfaceMethod.GetParameters()));
private static bool AreParamsEqualForOverloadResolution(
IEnumerable<ParameterInfo> paramsA, IEnumerable<ParameterInfo> paramsB)
{
var requiredParamsA = paramsA.Where(p => !p.IsOptional).OrderBy(p => p.Position).ToList();
var requiredParamsB = paramsB.Where(p => !p.IsOptional).OrderBy(p => p.Position).ToList();
if (requiredParamsA.Count != requiredParamsB.Count) return false;
for (var i = 0; i < requiredParamsA.Count; i++)
{
var paramA = requiredParamsA[i];
var paramB = requiredParamsB[i];
if (paramA.ParameterType != paramB.ParameterType) return false;
//TODO How do I determine type?
}
return true;
}
Также (не уверен, должен ли это быть отдельный Вопрос или нет), есть ли какой-нибудь более чистый способ сделать это, чем писать его самому - в идеале что-то в .Net, чтобы, если по какой-либо причине Microsoft решилаизменить то, что составляет сигнатуру метода, я могу просто обновить вместо того, чтобы менять свой код?