public void CanCreateInterfaceWithTypeArgs()
        {
            InterfaceDeclaration iface = new InterfaceDeclaration("ITrackPropertyChanges", new CodeDomTypeReference("Awish.Common.Models.Core.Company"));

            ClassDeclaration cdecl = new ClassDeclaration("Company");
            cdecl.Implements(iface);
            new CodeBuilder().GenerateCode(Console.Out, "Poops.McGee", cdecl);
        }
        private void AddPropertyChangedPlumbing(ClassDeclaration cs)
        {
            var iface = new InterfaceDeclaration("EightyProofSolutions.BlogEngine.Core.Models.ITrackPropertyChanges", new CodeDomTypeReference(cs.FullName));
            cs.Implements(iface);
            var pairCodeTypeReference = new CodeTypeReference("EightyProofSolutions.BlogEngine.Core.Pair", new CodeTypeReference("System.Object"), new CodeTypeReference("System.Object"));
            var changedPropertiesType = new CodeTypeReference("System.Collections.Generic.Dictionary");
            changedPropertiesType.TypeArguments.Add(typeof(string));
            changedPropertiesType.TypeArguments.Add(pairCodeTypeReference);

            var changedPropertiesField = new CodeMemberField();
            changedPropertiesField.Name = "_changedProperties";
            changedPropertiesField.Type = changedPropertiesType;
            changedPropertiesField.Attributes = MemberAttributes.Private;
            changedPropertiesField.InitExpression = new CodeObjectCreateExpression(changedPropertiesType);
            cs.Members.Add(changedPropertiesField);

            var changedPropertiesProperty = new CodeMemberProperty();
            changedPropertiesProperty.Name = "ChangedProperties";
            changedPropertiesProperty.PrivateImplementationType = new CodeTypeReference("EightyProofSolutions.BlogEngine.Core.Models.ITrackPropertyChanges");
            changedPropertiesProperty.Type = changedPropertiesType;
            changedPropertiesProperty.GetStatements.Add(new CodeMethodReturnStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "_changedProperties")));
            cs.Members.Add(changedPropertiesProperty);

            var changedMethod = new CodeMemberMethod();
            changedMethod.Name = "Changed";
            changedMethod.PrivateImplementationType = new CodeTypeReference("EightyProofSolutions.BlogEngine.Core.Models.ITrackPropertyChanges");
            changedMethod.Parameters.Add(new CodeParameterDeclarationExpression(typeof(string), "propertyName"));
            changedMethod.ReturnType = new CodeTypeReference("System.Boolean");
            changedMethod.Statements.Add(new CodeMethodReturnStatement(new CodeMethodInvokeExpression(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "_changedProperties"), "ContainsKey", new CodeArgumentReferenceExpression("propertyName"))));
            cs.Members.Add(changedMethod);

            var trackingChangesField = new CodeMemberField();
            trackingChangesField.Name = "_trackingChanges";
            trackingChangesField.Type = new CodeTypeReference("System.Boolean");
            trackingChangesField.InitExpression = new CodeSnippetExpression("true");
            cs.Members.Add(trackingChangesField);
            var trackingChangesProperty = new CodeMemberProperty();
            trackingChangesProperty.Name = "TrackingChanges";
            trackingChangesProperty.PrivateImplementationType = new CodeTypeReference("EightyProofSolutions.BlogEngine.Core.Models.ITrackPropertyChanges");
            trackingChangesProperty.Type = new CodeTypeReference("System.Boolean");
            trackingChangesProperty.GetStatements.Add(new CodeMethodReturnStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "_trackingChanges")));
            trackingChangesProperty.SetStatements.Add(new CodeAssignStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "_trackingChanges"), new CodeSnippetExpression("value")));
            cs.Members.Add(trackingChangesProperty);

            var propChangedEvent = new CodeMemberEvent();
            propChangedEvent.Name = "PropertyChanged";
            propChangedEvent.Type = new CodeTypeReference("System.ComponentModel.PropertyChangedEventHandler");
            propChangedEvent.Attributes = MemberAttributes.Public | MemberAttributes.Final;
            cs.Members.Add(propChangedEvent);

            var propChangedMethod = new CodeMemberMethod();
            propChangedMethod.Name = "OnPropertyChanged";
            propChangedMethod.PrivateImplementationType = new CodeTypeReference("EightyProofSolutions.BlogEngine.Core.Models.ITrackPropertyChanges");
            propChangedMethod.Parameters.Add(new CodeParameterDeclarationExpression(typeof(string), "propertyName"));
            propChangedMethod.Parameters.Add(new CodeParameterDeclarationExpression(typeof(object), "oldValue"));
            propChangedMethod.Parameters.Add(new CodeParameterDeclarationExpression(typeof(object), "newValue"));

            var iftrackchanges = new CodeConditionStatement(
                new CodeBinaryOperatorExpression(
                    new CodePropertyReferenceExpression(new CodeCastExpression("EightyProofSolutions.BlogEngine.Core.Models.ITrackPropertyChanges", new CodeThisReferenceExpression()), "TrackingChanges"),
                    CodeBinaryOperatorType.IdentityInequality,
                    new CodeSnippetExpression("true")));

            iftrackchanges.TrueStatements.Add(new CodeMethodReturnStatement());
            propChangedMethod.Statements.Add(iftrackchanges);

            var changedPropertyIndexer = new CodeIndexerExpression(
                new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "_changedProperties"));
            changedPropertyIndexer.Indices.Add(new CodeArgumentReferenceExpression("propertyName"));
            propChangedMethod.Statements.Add(new CodeAssignStatement(changedPropertyIndexer,
                new CodeObjectCreateExpression(pairCodeTypeReference,
                    new CodeArgumentReferenceExpression("oldValue"),
                    new CodeArgumentReferenceExpression("newValue"))));

            var ifeventnotnull = new CodeConditionStatement(
                new CodeBinaryOperatorExpression(
                    new CodeEventReferenceExpression(new CodeThisReferenceExpression(), "PropertyChanged"),
                    CodeBinaryOperatorType.IdentityInequality,
                    new CodeSnippetExpression("null")));

            ifeventnotnull.TrueStatements.Add(
                new CodeMethodInvokeExpression(
                    new CodeThisReferenceExpression(), "PropertyChanged",
                        new CodeThisReferenceExpression(),
                        new CodeObjectCreateExpression("System.ComponentModel.PropertyChangedEventArgs",
                            new CodeArgumentReferenceExpression("propertyName"))));
            propChangedMethod.Statements.Add(ifeventnotnull);

            cs.Members.Add(propChangedMethod);
        }