/// <summary> /// Beginnt den kompiliervorgang und erzeugt den Code und die Assembly. /// </summary> /// <param name="elementModel">Das Modell für das Element an dem ein Kontrakt definiert wurde.</param> private void GenerateCode(MemberBaseModel elementModel) { string sourceCodeFile = ContractController.Instance.CreateFileName(elementModel.Member.DeclaringType.Assembly, Resources.StrSourceCodeFielExt); string debugInformationFile = ContractController.Instance.CreateFileName(elementModel.Member.DeclaringType.Assembly, Resources.StrPdbFileExt); string contractAssemblyFile = ContractController.Instance.CreateFileName(elementModel.Member.DeclaringType.Assembly, Resources.StrAssemblyFileExt); // Der CheckContract Methode eine Exception werfen lassen wenn keine Kontraktmethode // gefunden wurde. mCheckContractMethodModel.Statements.Add(new CodeThrowExceptionStatement(new CodeObjectCreateExpression(new CodeTypeReference(typeof(ContractException)), new CodeExpression[] { new CodeBinaryOperatorExpression( new CodePrimitiveExpression(Resources.ExcCantFindMethodBegin), CodeBinaryOperatorType.Add, new CodeBinaryOperatorExpression( new CodeVariableReferenceExpression(Resources.StrParameterContractKey), CodeBinaryOperatorType.Add, new CodePrimitiveExpression(Resources.ExcCantFindMethodEnd)))}))); // Der GetOldValues Methode eine Exception werfen lassen wenn keine Kontraktmethode // gefunden wurde. mGetOldValuesMethodModel.Statements.Add(new CodeThrowExceptionStatement(new CodeObjectCreateExpression(new CodeTypeReference(typeof(ContractException)), new CodeExpression[] { new CodeBinaryOperatorExpression( new CodePrimitiveExpression(Resources.ExcCantFindMethodBegin), CodeBinaryOperatorType.Add, new CodeBinaryOperatorExpression( new CodeVariableReferenceExpression(Resources.StrParameterContractKey), CodeBinaryOperatorType.Add, new CodePrimitiveExpression(Resources.ExcCantFindMethodEnd)))}))); // Den CodeDomProvider instanzieren. CodeDomProvider provider = CodeDomProvider.CreateProvider(Microsoft.CSharp.CSharpCodeProvider.GetLanguageFromExtension(".cs")); CodeGeneratorOptions options = new CodeGeneratorOptions(); // Keine Leerzeilen zwischen den Member options.BlankLinesBetweenMembers = false; // geschweifte Klammer in eigener Zeile und NICHT am Ende der zugehörigen Anweisung options.BracingStyle = "C"; // Tabulator als Einrückungszeichen options.IndentString = "\t"; // Alles in der Reihenfolge erzeugen, wie es im Graph steht options.VerbatimOrder = true; // nix unnützes options.ElseOnClosing = false; // Den Compiler Parameter instanziieren. CompilerParameters parameters = new CompilerParameters(); // Referenzen einbinden // Die Contracted Assembly hinzufügen parameters.ReferencedAssemblies.Add(elementModel.Member.DeclaringType.Assembly.Location); // Alle Referenzen hinzufügen foreach (Assembly referenceAssembly in AssemblyController.Instance.GetReferencedAssemblies(elementModel.Member.DeclaringType.Assembly)) parameters.ReferencedAssemblies.Add(referenceAssembly.Location); // Angeben, dass in jedem Fall eine Datei erzeugt werden soll. parameters.GenerateInMemory = false; // Name der Assembly angeben parameters.OutputAssembly = contractAssemblyFile; #if(DEBUG) // Angeben dass eine Debugdatei erstellt werden soll (*.pdb) parameters.IncludeDebugInformation = true; #endif TextWriter stringWriter = null; try { stringWriter = File.CreateText(sourceCodeFile); provider.GenerateCodeFromCompileUnit(mAssemblyCompileUnit, stringWriter, options); } finally { if (stringWriter != null) stringWriter.Close(); } // Assembly aus Sourcecode Datei erzeugen. CompilerResults result = provider.CompileAssemblyFromFile(parameters, sourceCodeFile); if (result.Errors.Count != 0) { // Fehlermeldung ausgeben StringBuilder exceptionText = new StringBuilder(); foreach (CompilerError aError in result.Errors) { exceptionText.AppendLine(aError.ErrorText); } throw new Exception(exceptionText.ToString()); } // Dateien als ByteArray speichern #if(DEBUG) elementModel.PdbFile = ReadFile(debugInformationFile); elementModel.SourceCodeFile = ReadFile(sourceCodeFile); #endif elementModel.ContractAssembly = ReadFile(contractAssemblyFile); mSourceCodeGenerated = true; }
/// <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); }