Roslyn项目SymbolFinder空异常及方法引用获取技术咨询
Why
methodToSearchFor Throws a NullReferenceException & How to Use SymbolFinder Correctly Reasons for the Null Exception
Let’s walk through why you’re hitting that null error when trying to get methodToSearchFor:
- Case-sensitive metadata names: Roslyn’s
GetTypeByMetadataNameis strict about casing. Double-check that"ConsoleApp6.Person"matches your actual class’s full name exactly—namespace included, no typos in capitalization. - Failed project compilation: If your project has build errors,
GetCompilationAsync().Resultwill return a compilation that can’t resolve symbols properly. Always verify ifclassWithMethodToSearchForis null first; if it is, your compilation likely failed. - Empty member result:
GetMembers("Add")might return an empty sequence if no matching member exists. CallingFirst()on an empty sequence throws an exception—useFirstOrDefault()instead to handle this gracefully. - Entry point typo: Your
mainmethod is lowercase, but C# requires the entry point to bestatic void Main()(uppercase M). While this doesn’t directly cause the symbol issue, it can prevent your program from running as expected.
Proper Usage of SymbolFinder to Get Method References
Here’s a revised, robust version of your code that fixes the null issue and uses SymbolFinder correctly:
namespace consoleApp6 { public class Person { public int Add() { return 400; } // Corrected entry point casing static void Main() { string solutionPath = @"C:\Users\sslindia\source\repos\ConsoleApp6\ConsoleApp6.sln"; var msWorkspace = MSBuildWorkspace.Create(); // Check for solution load errors var solution = msWorkspace.OpenSolutionAsync(solutionPath).Result; if (msWorkspace.Diagnostics.Any(d => d.Severity == DiagnosticSeverity.Error)) { Console.WriteLine("Failed to load solution: " + string.Join("\n", msWorkspace.Diagnostics)); return; } var targetProject = solution.Projects.FirstOrDefault(x => x.Name == "ConsoleApp6"); if (targetProject == null) { Console.WriteLine("Target project 'ConsoleApp6' not found"); return; } var compilation = targetProject.GetCompilationAsync().Result; // Validate compilation succeeded var compilationErrors = compilation.GetDiagnostics().Where(d => d.Severity == DiagnosticSeverity.Error); if (compilationErrors.Any()) { Console.WriteLine("Compilation failed with errors:\n" + string.Join("\n", compilationErrors.Select(e => e.GetMessage()))); return; } var personClass = compilation.GetTypeByMetadataName("consoleApp6.Person"); // Match namespace casing exactly if (personClass == null) { Console.WriteLine("Person class not found in compilation"); return; } // Filter to only method symbols to avoid non-method matches var addMethod = personClass.GetMembers("Add").OfType<IMethodSymbol>().FirstOrDefault(); if (addMethod == null) { Console.WriteLine("Add method not found in Person class"); return; } // Retrieve method references and callers var references = SymbolFinder.FindReferencesAsync(addMethod, solution).Result; var callers = SymbolFinder.FindCallersAsync(addMethod, solution).Result; int totalReferences = references.Sum(r => r.Locations.Count()); Console.WriteLine($"Total references found: {totalReferences}"); // Optional: Print detailed caller info Console.WriteLine("\nCaller details:"); foreach (var caller in callers) { var firstLocation = caller.Locations.First(); Console.WriteLine($"- Caller: {caller.CallerSymbol.Name} | File: {firstLocation.Document.FilePath} | Line: {firstLocation.GetLineSpan().StartLinePosition.Line + 1}"); } } } }
Key Improvements:
- Step-by-step error checking: We validate every intermediate result (solution load, project existence, compilation success, etc.) to catch issues early and provide clear feedback.
- Targeted symbol filtering: Using
OfType<IMethodSymbol>()ensures we only retrieve method symbols, avoiding accidental matches with fields/properties that share the same name. - Safer LINQ operations:
FirstOrDefault()replacesFirst()to prevent exceptions when no matching elements are found. - Diagnostic checks: We surface solution and compilation errors, which are often the root cause of symbol resolution failures.
Quick Tips for SymbolFinder:
FindReferencesAsyncreturns all usages (declarations, calls, references), whileFindCallersAsyncfocuses specifically on places where the method is invoked.- For large solutions, use
awaitinstead of.Resultto avoid blocking the main thread (better async practice, even in console apps). - Always ensure your solution builds cleanly—Roslyn can’t resolve symbols correctly if there are unresolved errors.
内容的提问来源于stack exchange,提问作者Kabilan Kannan8
相关产品推荐
相关产品推荐

