I'm attempting to find all locations in a solution that calls the method IBus.Publish<T>
(from NServiceBus). So far this is working:
IMethodSymbol method = ... [IBus.Publish methodsymbol resolved];
var callers = method.FindCallers(solution, new CancellationToken());
This results in a IEnumerable<SymbolCallerInfo>
and I get all the correct references to this method.
How would I now go about to get the generic argument IBus.Publish
was called with? Do I have to parse the sourcetree manually, or does it exist some Roslyn magic I can leverage?
Example:
In my code I have:
IBus _bus;
_bus.Publish<IMyMessage>(msg => { msg.Text = "Hello world"});
I'm interested in getting the IMyMessage
type.
Greatly appreciate the help!
You can use a SemanticModel
to go from the SyntaxNode
for the call to the actual MethodSymbol
, and then you can just read the TypeArguments
property to get the TypeSymbol
s for the arguments. That will even work if the arguments aren't specified explicitly, since the SemanticModel
will perform type inference.
For example:
var callers = method.FindCallers(solution, CancellationToken.None);
foreach (var caller in callers)
{
foreach (var location in caller.Locations)
{
if (location.IsInSource)
{
var callerSemanticModel = solution
.GetDocument(location.SourceTree)
.GetSemanticModel();
var node = location.SourceTree.GetRoot()
.FindToken(location.SourceSpan.Start)
.Parent;
var symbolInfo = callerSemanticModel.GetSymbolInfo(node);
var calledMethod = symbolInfo.Symbol as IMethodSymbol;
if (calledMethod != null)
{
var arguments = calledMethod.TypeArguments;
}
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With