Exemplo n.º 1
0
            private void GenerateTypeConverter(CodeTypeDeclaration generatedType, Dictionary <ILiteral, string> fieldNames)
            {
                var dependents = generatedType.DependentTypes(true);

                if (dependents.Any(c => c.Name == generatedType.Name + "Converter") ||
                    fieldNames.All(field => field.Value == field.Key.Name))
                {
                    return;
                }

                var typeConverter = new CodeTypeDeclaration(generatedType.Name + "Converter");

                typeConverter.BaseTypes.Add(typeof(TypeConverter).ToTypeReference());
                var stringTypeRef = new CodeTypeOfExpression(typeof(string));

                var canConvertFromMethod = new CodeMemberMethod
                {
                    Name       = "CanConvertFrom",
                    Attributes = MemberAttributes.Public | MemberAttributes.Override,
                    ReturnType = new CodeTypeReference(typeof(bool))
                };

                canConvertFromMethod.Parameters.Add(new CodeParameterDeclarationExpression(typeof(ITypeDescriptorContext).ToTypeReference(), "context"));
                canConvertFromMethod.Parameters.Add(new CodeParameterDeclarationExpression(typeof(System.Type).ToTypeReference(), "sourceType"));
                var sourceTypeRef = new CodeArgumentReferenceExpression("sourceType");

                canConvertFromMethod.Statements.Add(new CodeMethodReturnStatement(new CodeBinaryOperatorExpression(sourceTypeRef, CodeBinaryOperatorType.IdentityEquality, stringTypeRef)));
                typeConverter.Members.Add(canConvertFromMethod);

                var canConvertTo = new CodeMemberMethod
                {
                    Name       = "CanConvertTo",
                    Attributes = MemberAttributes.Public | MemberAttributes.Override,
                    ReturnType = new CodeTypeReference(typeof(bool))
                };

                canConvertTo.Parameters.Add(new CodeParameterDeclarationExpression(typeof(ITypeDescriptorContext).ToTypeReference(), "context"));
                canConvertTo.Parameters.Add(new CodeParameterDeclarationExpression(typeof(System.Type), "destinationType"));
                var destinationTypeRef = new CodeArgumentReferenceExpression("destinationType");

                canConvertTo.Statements.Add(new CodeMethodReturnStatement(new CodeBinaryOperatorExpression(destinationTypeRef, CodeBinaryOperatorType.IdentityEquality, stringTypeRef)));
                typeConverter.Members.Add(canConvertTo);

                var typeRef        = generatedType.GetReferenceForType();
                var typeExpression = new CodeTypeReferenceExpression(typeRef);
                var convertFrom    = new CodeMemberMethod
                {
                    Name       = "ConvertFrom",
                    Attributes = MemberAttributes.Public | MemberAttributes.Override,
                    ReturnType = new CodeTypeReference(typeof(object))
                };

                convertFrom.Parameters.Add(new CodeParameterDeclarationExpression(typeof(ITypeDescriptorContext).ToTypeReference(), "context"));
                convertFrom.Parameters.Add(new CodeParameterDeclarationExpression(typeof(CultureInfo).ToTypeReference(), "culture"));
                convertFrom.Parameters.Add(new CodeParameterDeclarationExpression(typeof(object), "value"));
                var valueRef = new CodeArgumentReferenceExpression("value");
                var nullRef  = new CodePrimitiveExpression();

                convertFrom.Statements.Add(new CodeConditionStatement(new CodeBinaryOperatorExpression(valueRef, CodeBinaryOperatorType.IdentityEquality, nullRef),
                                                                      new CodeMethodReturnStatement(new CodeDefaultValueExpression(typeRef))));
                var valueString = new CodeVariableDeclarationStatement(typeof(string), "valueString", new CodeMethodInvokeExpression(valueRef, "ToString"));

                convertFrom.Statements.Add(valueString);
                var valueStringRef = new CodeVariableReferenceExpression(valueString.Name);

                foreach (var field in fieldNames)
                {
                    convertFrom.Statements.Add(new CodeConditionStatement(new CodeBinaryOperatorExpression(valueStringRef, CodeBinaryOperatorType.ValueEquality, new CodePrimitiveExpression(field.Key.Name)),
                                                                          new CodeMethodReturnStatement(new CodeFieldReferenceExpression(typeExpression, field.Value))));
                }
                convertFrom.Statements.Add(new CodeMethodReturnStatement(new CodeDefaultValueExpression(typeRef)));
                typeConverter.Members.Add(convertFrom);

                var convertTo = new CodeMemberMethod
                {
                    Name       = "ConvertTo",
                    Attributes = MemberAttributes.Public | MemberAttributes.Override,
                    ReturnType = new CodeTypeReference(typeof(object))
                };

                convertTo.Parameters.Add(new CodeParameterDeclarationExpression(typeof(ITypeDescriptorContext).ToTypeReference(), "context"));
                convertTo.Parameters.Add(new CodeParameterDeclarationExpression(typeof(CultureInfo).ToTypeReference(), "culture"));
                convertTo.Parameters.Add(new CodeParameterDeclarationExpression(typeof(object), "value"));
                convertTo.Parameters.Add(new CodeParameterDeclarationExpression(typeof(System.Type).ToTypeReference(), "destinationType"));
                convertTo.Statements.Add(new CodeConditionStatement(new CodeBinaryOperatorExpression(valueRef, CodeBinaryOperatorType.IdentityEquality, nullRef),
                                                                    new CodeMethodReturnStatement(nullRef)));
                var valueCasted = new CodeVariableDeclarationStatement(typeRef, "valueCasted", new CodeCastExpression(typeRef, valueRef));

                convertTo.Statements.Add(valueCasted);
                var valueCastedRef = new CodeVariableReferenceExpression(valueCasted.Name);

                foreach (var field in fieldNames)
                {
                    convertTo.Statements.Add(new CodeConditionStatement(new CodeBinaryOperatorExpression(valueCastedRef, CodeBinaryOperatorType.ValueEquality, new CodeFieldReferenceExpression(typeExpression, field.Value)),
                                                                        new CodeMethodReturnStatement(new CodePrimitiveExpression(field.Key.Name))));
                }
                convertTo.ThrowException <ArgumentOutOfRangeException>("value");
                typeConverter.Members.Add(convertTo);

                generatedType.AddAttribute(typeof(TypeConverterAttribute), new CodeTypeOfExpression(typeConverter.Name));
                dependents.Add(typeConverter);
            }