private static MemberDeclarationSyntax GenerateConstructor(WellKnownTypes wellKnownTypes, string className, List <FieldInfoMember> fields) { var body = new List <StatementSyntax>(); // Expressions for specifying binding flags. var bindingFlags = SymbolSyntaxExtensions.GetBindingFlagsParenthesizedExpressionSyntax( SyntaxKind.BitwiseOrExpression, BindingFlags.Instance, BindingFlags.NonPublic, BindingFlags.Public); var fieldUtils = IdentifierName("fieldUtils"); foreach (var field in fields) { // Get the field var fieldInfoField = IdentifierName(field.InfoFieldName); var fieldInfo = InvocationExpression(TypeOfExpression(field.Field.ContainingType.ToTypeSyntax()).Member("GetField")) .AddArgumentListArguments( Argument(field.Field.Name.ToLiteralExpression()), Argument(bindingFlags)); var fieldInfoVariable = VariableDeclarator(field.InfoFieldName).WithInitializer(EqualsValueClause(fieldInfo)); if (!field.IsGettableProperty || !field.IsSettableProperty) { body.Add(LocalDeclarationStatement( VariableDeclaration(wellKnownTypes.FieldInfo.ToTypeSyntax()).AddVariables(fieldInfoVariable))); } // Set the getter/setter of the field if (!field.IsGettableProperty) { var getterType = wellKnownTypes.Func_2.Construct(field.Field.ContainingType, field.SafeType).ToTypeSyntax(); var getterInvoke = CastExpression( getterType, InvocationExpression(fieldUtils.Member("GetGetter")).AddArgumentListArguments(Argument(fieldInfoField))); body.Add(ExpressionStatement( AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, IdentifierName(field.GetterFieldName), getterInvoke))); } if (!field.IsSettableProperty) { if (field.Field.ContainingType != null && field.Field.ContainingType.IsValueType) { var setterType = wellKnownTypes.ValueTypeSetter_2.Construct(field.Field.ContainingType, field.SafeType).ToTypeSyntax(); var getValueSetterInvoke = CastExpression( setterType, InvocationExpression(fieldUtils.Member("GetValueSetter")) .AddArgumentListArguments(Argument(fieldInfoField))); body.Add(ExpressionStatement( AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, IdentifierName(field.SetterFieldName), getValueSetterInvoke))); } else { var setterType = wellKnownTypes.Action_2.Construct(field.Field.ContainingType, field.SafeType).ToTypeSyntax(); var getReferenceSetterInvoke = CastExpression( setterType, InvocationExpression(fieldUtils.Member("GetReferenceSetter")) .AddArgumentListArguments(Argument(fieldInfoField))); body.Add(ExpressionStatement( AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, IdentifierName(field.SetterFieldName), getReferenceSetterInvoke))); } } } return (ConstructorDeclaration(className) .AddModifiers(Token(SyntaxKind.PublicKeyword)) .AddParameterListParameters( Parameter(fieldUtils.Identifier).WithType(wellKnownTypes.IFieldUtils.ToTypeSyntax())) .AddBodyStatements(body.ToArray())); }
private static ConstructorDeclarationSyntax GenerateConstructor(string simpleClassName, List <FieldDescription> fieldDescriptions) { var injected = fieldDescriptions.Where(f => f.IsInjected).ToList(); var parameters = injected.Select(f => Parameter(f.FieldName.ToIdentifier()).WithType(f.FieldType)); var fieldAccessorUtility = AliasQualifiedName("global", IdentifierName("Hagar")).Member("Utilities").Member("FieldAccessor"); IEnumerable <StatementSyntax> GetStatements() { foreach (var field in fieldDescriptions) { switch (field) { case GetterFieldDescription getter: yield return(InitializeGetterField(getter)); break; case SetterFieldDescription setter: yield return(InitializeSetterField(setter)); break; case FieldDescription _ when field.IsInjected: yield return(ExpressionStatement( AssignmentExpression( SyntaxKind.SimpleAssignmentExpression, ThisExpression().Member(field.FieldName.ToIdentifierName()), Unwrapped(field.FieldName.ToIdentifierName())))); break; } } } StatementSyntax InitializeGetterField(GetterFieldDescription getter) { var fieldInfo = GetFieldInfo(getter.Member.Field.ContainingType, getter.Member.Field.Name); var accessorInvoke = CastExpression( getter.FieldType, InvocationExpression(fieldAccessorUtility.Member("GetGetter")).AddArgumentListArguments(Argument(fieldInfo))); return(ExpressionStatement( AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, IdentifierName(getter.FieldName), accessorInvoke))); } StatementSyntax InitializeSetterField(SetterFieldDescription setter) { var field = setter.Member.Field; var fieldInfo = GetFieldInfo(field.ContainingType, field.Name); var accessorMethod = setter.IsContainedByValueType ? "GetValueSetter" : "GetReferenceSetter"; var accessorInvoke = CastExpression( setter.FieldType, InvocationExpression(fieldAccessorUtility.Member(accessorMethod)) .AddArgumentListArguments(Argument(fieldInfo))); return(ExpressionStatement( AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, IdentifierName(setter.FieldName), accessorInvoke))); } InvocationExpressionSyntax GetFieldInfo(INamedTypeSymbol containingType, string fieldName) { var bindingFlags = SymbolSyntaxExtensions.GetBindingFlagsParenthesizedExpressionSyntax( SyntaxKind.BitwiseOrExpression, BindingFlags.Instance, BindingFlags.NonPublic, BindingFlags.Public); return(InvocationExpression(TypeOfExpression(containingType.ToTypeSyntax()).Member("GetField")) .AddArgumentListArguments( Argument(fieldName.GetLiteralExpression()), Argument(bindingFlags))); } return(ConstructorDeclaration(simpleClassName) .AddModifiers(Token(SyntaxKind.PublicKeyword)) .AddParameterListParameters(parameters.ToArray()) .AddBodyStatements(GetStatements().ToArray())); ExpressionSyntax Unwrapped(ExpressionSyntax expr) { return(InvocationExpression( MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, IdentifierName("HagarGeneratedCodeHelper"), IdentifierName("UnwrapService")), ArgumentList(SeparatedList(new[] { Argument(ThisExpression()), Argument(expr) })))); } }