コード例 #1
0
ファイル: CodeDomGenerator.cs プロジェクト: mjul/diesel
        private static CodeTypeMember[] CreateEqualityOperatorOverloading(string eigenType, bool isValueType)
        {
            var nullGuardNecessary = !isValueType;

            var equality = new CodeMemberMethod()
            {
                Attributes = MemberAttributes.Public | MemberAttributes.Static,
                Name       = "operator ==",
                Parameters =
                {
                    new CodeParameterDeclarationExpression(eigenType, "left"),
                    new CodeParameterDeclarationExpression(eigenType, "right"),
                },
                ReturnType = new CodeTypeReference(typeof(bool)),
            };

            if (nullGuardNecessary)
            {
                equality.Statements.Add(
                    // if (Object.ReferenceEquals(null, left)) return Object.ReferenceEquals(null, right);
                    new CodeConditionStatement(
                        ExpressionBuilder.ObjectReferenceEqualsNull(new CodeArgumentReferenceExpression("left")),
                        new CodeMethodReturnStatement(
                            ExpressionBuilder.ObjectReferenceEqualsNull(
                                new CodeArgumentReferenceExpression("right")))));
            }
            equality.Statements.Add(
                // return left.Equals(right);
                new CodeMethodReturnStatement(
                    new CodeMethodInvokeExpression(
                        new CodeArgumentReferenceExpression("left"),
                        "Equals",
                        new CodeExpression[] { new CodeArgumentReferenceExpression("right") })));


            var disequality = new CodeMemberMethod()
            {
                Attributes = MemberAttributes.Public | MemberAttributes.Static,
                Name       = "operator !=",
                Parameters =
                {
                    new CodeParameterDeclarationExpression(eigenType, "left"),
                    new CodeParameterDeclarationExpression(eigenType, "right"),
                },
                ReturnType = new CodeTypeReference(typeof(bool)),
            };

            if (nullGuardNecessary)
            {
                disequality.Statements.Add(
                    // if (Object.ReferenceEquals(null, left)) return !Object.ReferenceEquals(null, right);
                    new CodeConditionStatement(
                        ExpressionBuilder.ObjectReferenceEqualsNull(new CodeArgumentReferenceExpression("left")),
                        new CodeMethodReturnStatement(
                            ExpressionBuilder.Negate(
                                ExpressionBuilder.ObjectReferenceEqualsNull(
                                    new CodeArgumentReferenceExpression("right"))))));
            }

            disequality.Statements.Add(
                // return (false == left.Equals(right));
                new CodeMethodReturnStatement(
                    new CodeBinaryOperatorExpression(
                        new CodePrimitiveExpression(false),
                        CodeBinaryOperatorType.ValueEquality,
                        new CodeMethodInvokeExpression(
                            new CodeArgumentReferenceExpression("left"),
                            "Equals",
                            new CodeExpression[] { new CodeArgumentReferenceExpression("right") }))));

            return(new CodeTypeMember[] { equality, disequality });
        }
コード例 #2
0
        private static CodeBinaryOperatorExpression ComparePropertyValueEqualityExpression(ArrayType propertyType,
                                                                                           String propertyName,
                                                                                           String otherVariableName)
        {
            // TODO: this should probably be a warning in the model
            if (propertyType.RankSpecifiers.Ranks.Count() > 1)
            {
                throw new InvalidOperationException(
                          "Cannot generate equality for Array Types with more than one rank-specifier.");
            }
            var rankSpecifier = propertyType.RankSpecifiers.Ranks.Single();

            if (rankSpecifier.Dimensions > 1)
            {
                throw new InvalidOperationException(
                          "Cannot generate equality for Array Type with more than one dimension");
            }

            // (this.Property.Length == other.Property.Length)
            // && Enumerable.Zip(a, b, (a, b) => Object.Equals(a, b)).All(areEqual => areEqual);

            var thisPropertyReference  = ExpressionBuilder.ThisPropertyReference(propertyName);
            var otherPropertyReference = OtherPropertyReference(propertyName, otherVariableName);

            var bothNull = new CodeBinaryOperatorExpression(CompareToNull(thisPropertyReference),
                                                            CodeBinaryOperatorType.BooleanAnd,
                                                            CompareToNull(otherPropertyReference));

            var bothNotNull = new CodeBinaryOperatorExpression(
                ExpressionBuilder.Negate(CompareToNull(thisPropertyReference)),
                CodeBinaryOperatorType.BooleanAnd,
                ExpressionBuilder.Negate(CompareToNull(otherPropertyReference)));

            var sameArrayLength = new CodeBinaryOperatorExpression(
                new CodePropertyReferenceExpression(thisPropertyReference, "Length"),
                CodeBinaryOperatorType.ValueEquality,
                new CodePropertyReferenceExpression(otherPropertyReference, "Length"));

            var zipExpression = new CodeMethodInvokeExpression(
                new CodeMethodReferenceExpression(
                    new CodeTypeReferenceExpression(typeof(Enumerable)),
                    "Zip"),
                thisPropertyReference,
                otherPropertyReference,
                new CodeSnippetExpression("(a, b) => Object.Equals(a,b)"));

            var zipPairwiseEquality =
                new CodeMethodInvokeExpression(
                    new CodeMethodReferenceExpression(
                        new CodeTypeReferenceExpression(typeof(Enumerable)),
                        "All"),
                    zipExpression,
                    new CodeSnippetExpression("areEqual => areEqual")
                    );

            return(new CodeBinaryOperatorExpression(
                       bothNull,
                       CodeBinaryOperatorType.BooleanOr,
                       new CodeBinaryOperatorExpression(
                           bothNotNull,
                           CodeBinaryOperatorType.BooleanAnd,
                           new CodeBinaryOperatorExpression(sameArrayLength,
                                                            CodeBinaryOperatorType.BooleanAnd, zipPairwiseEquality))));
        }
コード例 #3
0
ファイル: CodeDomGenerator.cs プロジェクト: mjul/diesel
        private static CodeTypeMember[] CreateEqualsOverloadingUsingEqualityOperator(string typeName, bool isValueType, IEnumerable <PropertyDeclaration> properties)
        {
            // if (ReferenceEquals(null, obj)) return false;
            // return obj is EmployeeId && Equals((EmployeeId) obj);
            const string parameterName        = "obj";
            var          objVariableReference = new CodeArgumentReferenceExpression(parameterName);
            var          ifReferenceEqualsNullObjReturnFalse =
                new CodeConditionStatement(
                    ExpressionBuilder.ObjectReferenceEqualsNull(objVariableReference),
                    new CodeStatement[]
            {
                new CodeMethodReturnStatement(new CodePrimitiveExpression(false))
            },
                    new CodeStatement[] { }
                    );

            var returnObjIsTypeNameAndThisEqualsObj =
                new CodeMethodReturnStatement(
                    new CodeBinaryOperatorExpression(
                        CreateTypeIsAssignableFrom(typeName, objVariableReference),
                        CodeBinaryOperatorType.BooleanAnd,
                        new CodeMethodInvokeExpression(
                            new CodeThisReferenceExpression(),
                            "Equals",
                            new CodeCastExpression(typeName, objVariableReference))
                        ));

            var equalsObject = new CodeMemberMethod()
            {
                Attributes = MemberAttributes.Public | MemberAttributes.Override,
                Name       = "Equals",
                Parameters = { new CodeParameterDeclarationExpression(typeof(object), parameterName) },
                ReturnType = new CodeTypeReference(typeof(bool)),
                Statements =
                {
                    ifReferenceEqualsNullObjReturnFalse,
                    returnObjIsTypeNameAndThisEqualsObj
                }
            };

            var compareExpressions = from property in properties
                                     select EqualityMethodsGenerator.ComparePropertyValueEqualityExpression(property, "other");

            var nullGuardSeed = isValueType
                                    ? (CodeExpression) new CodePrimitiveExpression(true)
                                    : ExpressionBuilder.Negate(
                ExpressionBuilder.ObjectReferenceEqualsNull(
                    new CodeVariableReferenceExpression("other")));

            var comparerExpressionJoinedWithAnd = compareExpressions.Aggregate(
                nullGuardSeed,
                (CodeExpression a, CodeExpression b) =>
                new CodeBinaryOperatorExpression(a, CodeBinaryOperatorType.BooleanAnd, b));

            var equalsTyped = new CodeMemberMethod()
            {
                Attributes = MemberAttributes.Public | MemberAttributes.Final,
                Name       = "Equals",
                Parameters = { new CodeParameterDeclarationExpression(new CodeTypeReference(typeName), "other") },
                ReturnType = new CodeTypeReference(typeof(bool)),
                Statements =
                {
                    // return this == other
                    new CodeMethodReturnStatement(comparerExpressionJoinedWithAnd)
                }
            };

            return(new CodeTypeMember[] { equalsTyped, equalsObject });
        }