Как получить вид параметра из ParameterInfo? - PullRequest
0 голосов
/ 25 марта 2019

Во-первых, чтобы подчеркнуть возможность проблемы 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 решилаизменить то, что составляет сигнатуру метода, я могу просто обновить вместо того, чтобы менять свой код?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...