/// <summary>
 /// Konstruktor
 /// </summary>
 /// <param name="requireContract">Der Kontrakt zur Eintrittsprüfung.</param>
 /// <param name="ensureContract">Der Kontrakt zur Austrittsprufung.</param>
 /// <param name="member">Das Element an dem der DbcAspect definiert wurde</param>
 /// <param name="accessType">Gibt an, bei welchem Zugriff der Kontrakt angewendet werden soll.</param>
 /// <param name="checkTime">Gibt an, zu welchem Zeitpunkt der Kontrakt angewendet werden soll.</param>
 /// <param name="contractClassName">Gibt den Namen der Kontraktklasse an.</param>
 /// <param name="exceptionType">Gibt den Typ der Exception an, die für den Nichterfüllungsfall geworfen werden soll.</param>
 /// <param name="exceptionString">Gibt den Exceptiontext an, der bei Nichterfüllung geworfen werden soll.</param>
 internal MethodModel(string requireContract, string ensureContract, MemberInfo member, AccessType accessType, CheckTime checkTime, string contractClassName, Type exceptionType, string exceptionString)
     : base(member, accessType, checkTime, contractClassName, exceptionType, exceptionString)
 {
     // Erzeugen und zuweisen der ContractModels.
     if (requireContract == ensureContract)
     {
         RequireContract = new ContractModel(requireContract);
         EnsureContract = RequireContract;
         ContractsAreEqual = true;
         return;
     }
     if (!string.IsNullOrEmpty(requireContract))
         RequireContract = new ContractModel(requireContract);
     if (!string.IsNullOrEmpty(ensureContract))
         EnsureContract = new ContractModel(ensureContract);
 }
 /// <summary>
 /// Konstruktor
 /// </summary>
 /// <param name="getContract">Der Kontrakt der beim Lesezugriff geprüft wird.</param>
 /// <param name="setContract">Der Kontrakt der beim Schreibzugriff geprüft wird.</param>
 /// <param name="member">Das Element an dem der DbcAspect definiert wurde</param>
 /// <param name="accessType">Gibt an, bei welchem Zugriff der Kontrakt angewendet werden soll.</param>
 /// <param name="checkTime">Gibt an, zu welchem Zeitpunkt der Kontrakt angewendet werden soll.</param>
 /// <param name="contractClassName">Gibt den Namen der Kontraktklasse an.</param>
 /// <param name="exceptionType">Gibt den Typ der Exception an, die für den Nichterfüllungsfall geworfen werden soll.</param>
 /// <param name="exceptionString">Gibt den Exceptiontext an, der bei Nichterfüllung geworfen werden soll.</param>
 internal FieldModel(string getContract, string setContract, MemberInfo member, AccessType accessType, CheckTime checkTime, string contractClassName, Type exceptionType, string exceptionString)
     : base(member, accessType, checkTime, contractClassName, exceptionType, exceptionString)
 {
     // Erzeugen und zuweisen der ContractModels.
     if (getContract == setContract)
     {
         GetContract = new ContractModel(getContract);
         SetContract = GetContract;
         ContractsAreEqual = true;
         return;
     }
     if (!string.IsNullOrEmpty(getContract))
         GetContract = new ContractModel(getContract);
     if (!string.IsNullOrEmpty(setContract))
         SetContract = new ContractModel(setContract);
 }
        /// <summary>
        /// Fügt eine weitere Kontrakt Methode der zu erzeugenden Klasse hinzu.
        /// </summary>
        /// <param name="contract">ContractModel mit allen nötigen Daten</param>
        /// <param name="contractedElement">Das Element an dem der Kontrakt definiert wurde.</param>
        /// <param name="exceptionType">Übergibt den Typ der Exception, der geworfen werden soll wenn der Kontrakt nicht erfüllt wird.</param>
        /// <param name="exceptionString">Übergibt den Text der Exception, der geworfen werden soll wenn der Kontrakt nicht erfüllt wird.</param>
        /// <returns>CodeMemberMethod Objekt mit der Kontraktprüfung.</returns>
        private CodeMemberMethod AddContractMethod(ContractModel contract, MemberInfo contractedElement, Type exceptionType, string exceptionString)
        {
            //Methode anlegen
            CodeMemberMethod contractMethod = new CodeMemberMethod();
            contractMethod.Name = contract.ContractKey;
            contractMethod.ReturnType = new CodeTypeReference(typeof(void));
            contractMethod.Attributes = MemberAttributes.Public | MemberAttributes.Final;

            // Übergabeparameter festlegen
            contractMethod.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(object[])), Resources.StrParameterContractArguments));
            contractMethod.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(object)), Resources.StrParameterInstance));
            contractMethod.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(object)), Resources.StrParameterMethodResult));
            contractMethod.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(Type[])), Resources.StrParameterGenericTypes));
            if (contract.OldValueExist)
                contractMethod.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(object[])), Resources.StrParameterOldValues));

            //if Statement erzeugen
            CodeConditionStatement contractStatement = new CodeConditionStatement();
            contractStatement.Condition = new CodeSnippetExpression(contract.ConvertedContract);

            //return hinzufügen
            contractStatement.TrueStatements.Add(new CodeMethodReturnStatement());

            //Exception erzeugen
            string fullMethodName = contractedElement.DeclaringType.Namespace + "." + contractedElement.DeclaringType.Name + "." + contractedElement.Name;
            if (exceptionType == null)
                exceptionType = typeof(ContractException);
            if (string.IsNullOrEmpty(exceptionString))
                exceptionString = string.Format(CultureInfo.CurrentCulture, Resources.ExcContractNotValid, new object[] { contract.Contract, fullMethodName });
            CodeThrowExceptionStatement throwContractException = new CodeThrowExceptionStatement(new CodeObjectCreateExpression(new CodeTypeReference(exceptionType), new CodeExpression[] {new CodePrimitiveExpression(exceptionString )}));

            // Try Catch um diese Methode legen
            CodeTryCatchFinallyStatement tryContrainer = new CodeTryCatchFinallyStatement();
            tryContrainer.TryStatements.Add(contractStatement);

            // Catch Clauses erzeugen
            CodeCatchClause exceptionClause = new CodeCatchClause(Resources.StrParameterException);
            exceptionClause.CatchExceptionType = new CodeTypeReference(typeof(Exception));
            exceptionClause.Statements.Add(new CodeThrowExceptionStatement(new CodeObjectCreateExpression(new CodeTypeReference(typeof(ContractException)), new CodeExpression[] { new CodePrimitiveExpression(string.Format(CultureInfo.CurrentCulture, Resources.ExcErrorInContract, new object[] { contract.Contract, fullMethodName })), new CodeVariableReferenceExpression(Resources.StrParameterException) })));

            tryContrainer.CatchClauses.Add(exceptionClause);

            // Den kompletten Inhalt der Methode zuordnen
            contractMethod.Statements.Add(tryContrainer);
            contractMethod.Statements.Add(throwContractException);

            return contractMethod;
        }
        /// <summary>
        /// Erzeugt eine Element basierte GetOldValue Methode um die als alten Werte gekennzeichneten 
        /// Werte für einen Kontakt zu laden.
        /// </summary>
        /// <param name="contract">ContractModel mit allen nötigen Daten</param>
        /// <param name="contractedElement">Das Element an dem der Kontrakt definiert wurde.</param>
        /// <returns>CodeMemberMethod Objekt mit der dem OldValues als Rückgabewerte.</returns>
        private CodeMemberMethod AddGetOldValueMethod(ContractModel contract, MemberInfo contractedElement)
        {
            //Methode anlegen
            CodeMemberMethod getOldValueMethod = new CodeMemberMethod();
            getOldValueMethod.Name = contract.GetOldValueKey;
            getOldValueMethod.ReturnType = new CodeTypeReference(typeof(object[]));
            getOldValueMethod.Attributes = MemberAttributes.Public | MemberAttributes.Final;

            // Übergabeparameter festlegen
            getOldValueMethod.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(object[])), Resources.StrParameterContractArguments));
            getOldValueMethod.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(object)), Resources.StrParameterInstance));
            getOldValueMethod.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(Type[])), Resources.StrParameterGenericTypes));

            // Try Catch um diese Methode legen
            CodeTryCatchFinallyStatement tryContrainer = new CodeTryCatchFinallyStatement();
            foreach (string expression in contract.GetOldValuesStatements)
                tryContrainer.TryStatements.Add(new CodeSnippetExpression(expression));

            string fullMethodName = contractedElement.DeclaringType.Namespace + "." + contractedElement.DeclaringType.Name + "." + contractedElement.Name;
            // Catch Clauses erzeugen
            CodeCatchClause exceptionClause = new CodeCatchClause(Resources.StrParameterException);
            exceptionClause.CatchExceptionType = new CodeTypeReference(typeof(Exception));
            exceptionClause.Statements.Add(new CodeThrowExceptionStatement(	new CodeObjectCreateExpression(new CodeTypeReference(typeof(ContractException)), new CodeExpression[] { new CodePrimitiveExpression(string.Format(CultureInfo.CurrentCulture, Resources.ExcErrorInContract, new object[] {contract.Contract, fullMethodName} ) ), new CodeVariableReferenceExpression(Resources.StrParameterException)})));

            tryContrainer.CatchClauses.Add(exceptionClause);

            // Den kompletten Inhalt der Methode zuordnen
            getOldValueMethod.Statements.Add(tryContrainer);

            return getOldValueMethod;
        }
        /// <summary>
        /// Fügt eine weiter Kontraktprüfung der zu erzeugenden Klasse bzw. Assembly hinzu.
        /// </summary>
        /// <param name="contractModel">Modell mit allen relevanten Daten zum Kontrakt</param>
        /// <param name="aspectModel">Modell mit allen relevanten Daten zum Aspekt der den Kontrakt prüft</param>
        /// <returns>Sofern es sich um den letzten Aspekt handelt</returns>
        internal void AddContract(ContractModel contractModel, MemberBaseModel aspectModel)
        {
            if (!Started)
                StartContractGenerator(aspectModel.ContractClassName, aspectModel.Member.DeclaringType.Assembly);

            DbcAspectCurrentCount++;

            // Den Contract in einen gültigen Ausdruck übersetzen
            //ExpressionController exprController = new ExpressionController();
            //ExpressionModel exprModel = exprController.ConvertExpression(contractModel, aspectModel.Member);

            CodeMemberMethod contractMethod = AddContractMethod(contractModel, aspectModel.Member, aspectModel.ExceptionType, aspectModel.ExceptionString);
            mClassModel.Members.Add(contractMethod);
            //Methodenaufruf in der CheckContract Methode erzeugen.
            CodeConditionStatement contractCondition = AddContractMethodCall(contractModel.ContractKey, contractModel.OldValueExist);
            mCheckContractMethodModel.Statements.Add(contractCondition);

            if (contractModel.OldValueExist)
            {
                CodeMemberMethod getOldValueMethod = AddGetOldValueMethod(contractModel, aspectModel.Member);
                mClassModel.Members.Add(getOldValueMethod);
                //Methodenaufruf in der GetOldValue Methode erzeugen.
                CodeConditionStatement getOldValueCondition = AddGetOldValueMethodCall(contractModel.GetOldValueKey);
                mGetOldValuesMethodModel.Statements.Add(getOldValueCondition);
            }

            // Da es sich um den letzten Kontrakt handelt die Assemlby erzeugen und
            // in das ContractModel speichern.
            if ((DbcAspectCount == DbcAspectCurrentCount)
                && (!SourceCodeGenerated))
                //System.Windows.Forms.MessageBox.Show("Erzeugen des Codes");
                GenerateCode(aspectModel);
        }