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); } }