Esempio n. 1
0
        private void ProcessPropertyAccessors(BasePropertyDeclarationSyntax node, string propertyDeclaringTypeVar, string propName, string propertyType, string propDefVar, List <string> parameters)
        {
            var propInfo      = (IPropertySymbol)Context.SemanticModel.GetDeclaredSymbol(node);
            var declaringType = node.ResolveDeclaringType();

            foreach (var accessor in node.AccessorList.Accessors)
            {
                var accessorModifiers = node.Modifiers.MethodModifiersToCecil(ModifiersToCecil, "MethodAttributes.SpecialName", propInfo.GetMethod ?? propInfo.SetMethod);
                switch (accessor.Keyword.Kind())
                {
                case SyntaxKind.GetKeyword:
                    var getMethodVar = TempLocalVar(propertyDeclaringTypeVar + "_get_");
                    Context.DefinitionVariables.RegisterMethod(declaringType.Identifier.Text, $"get_{propName}", parameters?.ToArray(), getMethodVar);

                    AddCecilExpression($"var {getMethodVar} = new MethodDefinition(\"get_{propName}\", {accessorModifiers}, {propertyType});");
                    parameters.ForEach(paramVar => AddCecilExpression($"{getMethodVar}.Parameters.Add({paramVar});"));
                    AddCecilExpression($"{propertyDeclaringTypeVar}.Methods.Add({getMethodVar});");

                    AddCecilExpression($"{getMethodVar}.Body = new MethodBody({getMethodVar});");
                    AddCecilExpression($"{propDefVar}.GetMethod = {getMethodVar};");

                    if (propInfo.ContainingType.TypeKind == TypeKind.Interface)
                    {
                        break;
                    }

                    var ilVar          = TempLocalVar("ilVar_get_");
                    var ilProcessorExp = $"var {ilVar} = {getMethodVar}.Body.GetILProcessor();";

                    AddCecilExpression(ilProcessorExp);
                    if (accessor.Body == null)     //is this an auto property ?
                    {
                        AddBackingFieldIfNeeded(accessor);

                        AddCilInstruction(ilVar, OpCodes.Ldarg_0);     // TODO: This assumes instance properties...
                        AddCilInstruction(ilVar, OpCodes.Ldfld, MakeGenericTypeIfAppropriate(propInfo, backingFieldVar, propertyDeclaringTypeVar));

                        AddCilInstruction(ilVar, OpCodes.Ret);
                    }
                    else
                    {
                        StatementVisitor.Visit(Context, ilVar, accessor.Body);
                    }

                    break;

                case SyntaxKind.SetKeyword:
                    var setMethodVar = TempLocalVar(propertyDeclaringTypeVar + "_set_");
                    var localParams  = new List <string>(parameters);
                    localParams.Add(Context.GetTypeInfo(node.Type).Type.Name);     // Setters always have at least one `value` parameter.
                    Context.DefinitionVariables.RegisterMethod(declaringType.Identifier.Text, $"set_{propName}", localParams.ToArray(), setMethodVar);
                    var ilSetVar = TempLocalVar("ilVar_set_");

                    AddCecilExpression($"var {setMethodVar} = new MethodDefinition(\"set_{propName}\", {accessorModifiers}, {Context.TypeResolver.ResolvePredefinedType("Void")});");
                    parameters.ForEach(paramVar => AddCecilExpression($"{setMethodVar}.Parameters.Add({paramVar});"));
                    AddCecilExpression($"{propertyDeclaringTypeVar}.Methods.Add({setMethodVar});");

                    AddCecilExpression($"{setMethodVar}.Body = new MethodBody({setMethodVar});");
                    AddCecilExpression($"{propDefVar}.SetMethod = {setMethodVar};");

                    AddCecilExpression($"{setMethodVar}.Parameters.Add(new ParameterDefinition({propertyType}));");
                    AddCecilExpression($"var {ilSetVar} = {setMethodVar}.Body.GetILProcessor();");

                    if (propInfo.ContainingType.TypeKind == TypeKind.Interface)
                    {
                        break;
                    }

                    if (accessor.Body == null)     //is this an auto property ?
                    {
                        AddBackingFieldIfNeeded(accessor);

                        AddCilInstruction(ilSetVar, OpCodes.Ldarg_0);     // TODO: This assumes instance properties...
                        AddCilInstruction(ilSetVar, OpCodes.Ldarg_1);
                        AddCilInstruction(ilSetVar, OpCodes.Stfld, MakeGenericTypeIfAppropriate(propInfo, backingFieldVar, propertyDeclaringTypeVar));
                    }
                    else
                    {
                        StatementVisitor.Visit(Context, ilSetVar, accessor.Body);
                    }

                    AddCilInstruction(ilSetVar, OpCodes.Ret);
                    break;
                }
            }

            void AddBackingFieldIfNeeded(AccessorDeclarationSyntax accessor)
            {
                if (backingFieldVar != null)
                {
                    return;
                }

                backingFieldVar = TempLocalVar("bf");
                var backingFieldName = $"<{propName}>k__BackingField";
                var backingFieldExps = new[]
                {
                    $"var {backingFieldVar} = new FieldDefinition(\"{backingFieldName}\", {ModifiersToCecil("FieldAttributes", accessor.Modifiers, "Private")}, {propertyType});",
                    $"{propertyDeclaringTypeVar}.Fields.Add({backingFieldVar});"
                };

                AddCecilExpressions(backingFieldExps);
            }
        }