I am trying to use Roslyn to get the reference to the symbol (FieldSymbol) for backing field of the property, but AssociatedPropertyOrEvent is null. Here is the unit test that fails.
[Test]
public void Get_BackingField_for_Property()
{
var sourceCode = @" public class Player
{
private Person _MyPerson;
public virtual Person MyPerson
{
get { return _MyPerson; }
}
public virtual void Set(Person person)
{
_MyPerson = person;
}
}";
var syntaxTree = SyntaxTree.ParseText(sourceCode);
var mscorlib = MetadataReference.CreateAssemblyReference(
"mscorlib");
var compilation = Compilation.Create("HelloWorld")
.AddReferences(mscorlib)
.AddSyntaxTrees(syntaxTree);
//var semanticModel = compilation.GetSemanticModel(syntaxTree);
var classSymbol =
compilation.GetTypeByMetadataName("Player");
Assert.That(classSymbol,Is.Not.Null, "class");
var propertySymbol = classSymbol.GetMembers().Where(x => x.Kind == SymbolKind.Property);
Assert.That(propertySymbol, Is.Not.Null, "property");
var backingField = classSymbol.GetMembers().Where(x=>x.Kind== SymbolKind.Field).Cast<FieldSymbol>().First();
Assert.That(backingField.AssociatedPropertyOrEvent, Is.Not.Null,"backing field");
Update: For anybody trying to do the same INotifyPropertyChaged sample has code that gets backing field of the property. I modified it to fit my needs. Here is the code
internal static IFieldSymbol GetBackingField(this IPropertySymbol property, ISemanticModel semanticModel)
{
var propertyDelcarationSyntax = (PropertyDeclarationSyntax)property.DeclaringSyntaxNodes.First();
var getter = propertyDelcarationSyntax.AccessorList.Accessors.First(a => a.Kind == SyntaxKind.GetAccessorDeclaration);
return GetBackingFieldFromGetter(getter, semanticModel);
}
private static IFieldSymbol GetBackingFieldFromGetter(AccessorDeclarationSyntax getter, ISemanticModel semanticModel)
{
// The getter should have a body containing a single return of a backing field.
if (getter.Body == null)
{
throw new Exception("Missing a getter body for property " + semanticModel.GetDeclaredSymbol(getter.Parent).Name);
}
var statements = getter.Body.Statements;
if (statements.Count != 1)
{
throw new Exception("Getter body has more then one statement for property " + semanticModel.GetDeclaredSymbol(getter.Parent).Name);
}
var returnStatement = statements.Single() as ReturnStatementSyntax;
if (returnStatement == null || returnStatement.Expression == null)
{
throw new Exception("Getter body is missing a return statement for property " + semanticModel.GetDeclaredSymbol(getter.Parent).Name);
}
return semanticModel.GetSymbolInfo(returnStatement.Expression).Symbol as IFieldSymbol;
}