C # Как я могу обнаружить подписку EvenHandler в Roslyn - PullRequest
0 голосов
/ 23 января 2019

Я пишу пользовательское правило анализатора с использованием Roslyn.

Я хочу найти метод, который является обработчиком для какого-либо события (через подписку). Как это:

public class Counter
{
    public event EventHandler ThresholdReached;
}

public class TestEvent
{
    public TestEvent()
    {
        Counter с = new Counter();
        с.ThresholdReached += OnThresholdReached;
    }

    private void OnThresholdReached(object sender, EventArgs e)
    {

    }
}

В моей реализации это выглядит так:

    private static void HandleMethodDeclaration(SyntaxNodeAnalysisContext context)
    {
        MethodDeclarationSyntax methodDeclaration = (MethodDeclarationSyntax)context.Node;
        if (methodDeclaration.Identifier.IsMissing)
        {
            return;
        }

        IMethodSymbol methodSymbol = context.SemanticModel.GetDeclaredSymbol(methodDeclaration);

    }

Я не знаю, как обнаружить, что OnThresholdReached является подпиской на Событие ThresholdReached . Если кто-то знает, как это сделать, помогите пожалуйста =)

1 Ответ

0 голосов
/ 24 января 2019

В анализаторе вы не можете только узнать, взглянув на MethodDeclarationSyntax, преобразован ли этот метод в делегат или нет. Из-за этого вы не можете знать (только глядя на MethodDeclarationSyntax), передан ли этот делегат добавителю доступа события или нет.

Прежде всего, помните, что анализатор Roslyn может видеть только использования в текущей сборке (проекте). Если ваш метод преобразован в делегат в другой сборке, анализатор не сможет увидеть это.

Во-вторых, помните, что

с.ThresholdReached += OnThresholdReached;

может быть выражено как

EventHandler handler = OnThresholdReached;
с.ThresholdReached += handler;

Если вы хотите обнаружить только первый случай, вы можете посмотреть AssignmentExpressionSyntax экземпляры вида SyntaxKind.AddAssignmentExpression и проанализировать их.

Если вы хотите обнаружить все случаи, когда группа методов преобразуется в делегат, вам необходимо просмотреть все экземпляры типа SimpleNameSyntax и проанализировать их следующим образом:

void Analyze(SyntaxNodeAnalysisContext context)
{
    var node = context.Node as SimpleNameSyntax;

    // we're only interested in delegates
    var type = context.SemanticModel.GetTypeInfo(node, context.CancellationToken).ConvertedType;

    if (type == null || type.TypeKind != TypeKind.Delegate)
    {
        return;
    }

    // we're only interested in methods from the current assembly
    var symbol = context.SemanticModel.GetSymbolInfo(node, context.CancellationToken).Symbol;

    if (symbol == null ||
        symbol.Kind != SymbolKind.Method ||
        !symbol.ContainingAssembly.Equals(context.SemanticModel.Compilation.Assembly))
    {
        return;
    }

    // now you know symbol is a method in the same assembly, that is converted to a delegate
}

Чтобы найти исходный код для этого метода, см. https://stackoverflow.com/a/45362532/1403794.

...