简体   繁体   English

如何获取属性的后备字段(AssociatedPropertyOrEvent为null)?

[英]How to get the backing field for the property (AssociatedPropertyOrEvent is null)?

I am trying to use Roslyn to get the reference to the symbol (FieldSymbol) for backing field of the property, but AssociatedPropertyOrEvent is null. 我正在尝试使用Roslyn来获取对该属性的支持字段的符号(FieldSymbol)的引用,但是AssociatedPropertyOrEvent为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. 更新:对于尝试执行相同操作的任何人,INotifyPropertyChaged示例都具有获取属性的支持字段的代码。 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;
}

The documentation for AssociatedPropertyOrEvent says: AssociatedPropertyOrEvent的文档说:

If this field serves as a backing variable for an automatically generated property or a field-like event, returns that property/event. 如果此字段用作自动生成的属性或类字段事件的后备变量,则返回该属性/事件。 Otherwise returns null. 否则返回null。

Since your field has no relation to any autoproperties, AssociatedPropertyOrEvent correctly returns null . 由于您的字段与任何autoproperties无关,因此AssociatedPropertyOrEvent正确返回null

In general, what you're asking is impossible, because there could be many properties that access the same field. 一般来说,你所要求的是不可能的,因为可能有许多属性访问同一个字段。

You can only go the other way with the current API. 您只能使用当前的API进行其他方式。 Use GetMembers to get all of them, and then find the field whose AssociatedPropertyOrEvent is the property you want. 使用GetMembers获取所有这些,然后找到其AssociatedPropertyOrEvent是您想要的属性的字段。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM