//--------------------------------------------------------------------- // // Copyright (c) Microsoft Corporation. All rights reserved. // // // @owner [....] // @backupOwner [....] //--------------------------------------------------------------------- //#define ENABLE_TEMPLATE_DEBUGGING using System.CodeDom.Compiler; using System.Collections.Generic; using System.Data.Entity.Design.Common; using System.Data.Entity.Design.SsdlGenerator; using System.Data.Metadata.Edm; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.Versioning; using System.Threading; using System.Xml; namespace System.Data.Entity.Design { public class EntityCodeGenerator { private LanguageOption _languageOption = LanguageOption.GenerateCSharpCode; private EdmToObjectNamespaceMap _edmToObjectNamespaceMap = new EdmToObjectNamespaceMap(); public EntityCodeGenerator(LanguageOption languageOption) { _languageOption = EDesignUtil.CheckLanguageOptionArgument(languageOption, "languageOption"); } public LanguageOption LanguageOption { get { return _languageOption; } set { _languageOption = EDesignUtil.CheckLanguageOptionArgument(value, "value"); } } /// /// Gets the map entries use to customize the namespace of .net types that are generated /// and referenced by the generated code /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Edm")] public EdmToObjectNamespaceMap EdmToObjectNamespaceMap { get { return _edmToObjectNamespaceMap; } } /// /// Creates a source code file that contains object layer code generated from the specified conceptual schema definition /// language (CSDL) file. The list of schema file paths is used to resolve any references contained in the CSDL file. /// Note that the targetEntityFrameworkVersion parameter uses internal EntityFramework version numbers as described /// in the class. /// /// The path of the CSDL file. /// The path of the file that contains the generated object layer code. /// /// A list of schema file paths that can be used to resolve any references in the source schema (the CSDL file). /// If the source schema does not have any dependencies, pass in an empty list. /// /// The internal Entity Framework version that is being targeted. /// A list of objects that contains any generated errors. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Edm")] [ResourceExposure(ResourceScope.Machine)] // for sourceEdmSchemaFilePath, targetPath and additionalEdmSchema which are machine resources [ResourceConsumption(ResourceScope.Machine)] // for InternalGenerateCode method call. But the path is not created in this method. public IList GenerateCode(string sourceEdmSchemaFilePath, string targetPath, IEnumerable additionalEdmSchemaFilePaths, Version targetEntityFrameworkVersion) { EDesignUtil.CheckTargetEntityFrameworkVersionArgument(targetEntityFrameworkVersion, "targetEntityFrameworkVersion"); EntityUtil.CheckStringArgument(sourceEdmSchemaFilePath, "sourceEdmSchemaFilePath"); EDesignUtil.CheckArgumentNull(additionalEdmSchemaFilePaths, "additionalEdmSchemaFilePaths"); EntityUtil.CheckStringArgument(targetPath, "targetPath"); EDesignUtil.CheckTargetEntityFrameworkVersionArgument(targetEntityFrameworkVersion, "targetEntityFrameworkVersion"); return InternalGenerateCode(sourceEdmSchemaFilePath, new LazyTextWriterCreator(targetPath), additionalEdmSchemaFilePaths, targetEntityFrameworkVersion); } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Edm")] [ResourceExposure(ResourceScope.Machine)] // for sourceEdmSchemaFilePath, targetPath and additionalEdmSchema which are machine resources [ResourceConsumption(ResourceScope.Machine)] // for InternalGenerateCode method call. But the path is not created in this method. public IList GenerateCode(string sourceEdmSchemaFilePath, string targetPath, IEnumerable additionalEdmSchemaFilePaths) { Version targetFrameworkVersion; IList errors = GetMinimumTargetFrameworkVersion(sourceEdmSchemaFilePath, out targetFrameworkVersion); if (errors.Where(e => e.Severity == EdmSchemaErrorSeverity.Error).Any()) { return errors; } return errors.Concat(GenerateCode(sourceEdmSchemaFilePath, targetPath, additionalEdmSchemaFilePaths, targetFrameworkVersion)).ToList(); } /// /// Creates a source code file that contains the object layer code generated from the specified conceptual schema /// definition language (CSDL) file. Note that the targetEntityFrameworkVersion parameter uses internal Entity /// Framework version numbers as described in the class. /// /// The path of the CSDL file. /// The path of the file that contains the generated object layer code. /// The internal Entity Framework version that is being targeted. /// A list of objects that contains any generated errors. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Edm")] [ResourceExposure(ResourceScope.Machine)] // for sourceEdmSchemaFilePath and targetPath which are Machine resources [ResourceConsumption(ResourceScope.Machine)] // for InternalGenerateCode method call. But the path is not created in this method. public IList GenerateCode(string sourceEdmSchemaFilePath, string targetPath, Version targetEntityFrameworkVersion) { EntityUtil.CheckStringArgument(sourceEdmSchemaFilePath, "sourceEdmSchemaFilePath"); EntityUtil.CheckStringArgument(targetPath, "targetPath"); EDesignUtil.CheckTargetEntityFrameworkVersionArgument(targetEntityFrameworkVersion, "targetEntityFrameworkVersion"); return InternalGenerateCode(sourceEdmSchemaFilePath, new LazyTextWriterCreator(targetPath), null, targetEntityFrameworkVersion); } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Edm")] [ResourceExposure(ResourceScope.Machine)] // for sourceEdmSchemaFilePath and targetPath which are Machine resources [ResourceConsumption(ResourceScope.Machine)] // for InternalGenerateCode method call. But the path is not created in this method. public IList GenerateCode(string sourceEdmSchemaFilePath, string targetPath) { Version targetFrameworkVersion; IList errors = GetMinimumTargetFrameworkVersion(sourceEdmSchemaFilePath, out targetFrameworkVersion); if (errors.Where(e => e.Severity == EdmSchemaErrorSeverity.Error).Any()) { return errors; } return errors.Concat(GenerateCode(sourceEdmSchemaFilePath, targetPath, targetFrameworkVersion)).ToList(); } /// /// Generates object layer code using the conceptual schema definition language (CSDL) specified in the /// XmlReader object, and outputs the generated code to a TextWriter. /// Note that the targetEntityFrameworkVersion parameter uses internal EntityFramework version numbers as /// described in the class. /// /// An XmlReader that contains the CSDL. /// The TextWriter to which the object layer code is written. /// The internal Entity Framework version that is being targeted. /// A list of objects that contains any generated errors. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Edm")] [ResourceConsumption(ResourceScope.Machine)] // temp file creation, and passing to InternalGenerateCode public IList GenerateCode(XmlReader sourceEdmSchema, TextWriter target, Version targetEntityFrameworkVersion) { EDesignUtil.CheckArgumentNull(sourceEdmSchema, "sourceEdmSchema"); EDesignUtil.CheckArgumentNull(target, "target"); EDesignUtil.CheckTargetEntityFrameworkVersionArgument(targetEntityFrameworkVersion, "targetEntityFrameworkVersion"); Version schemaVersion; if (!IsValidSchema(sourceEdmSchema, out schemaVersion)) { return new List() { CreateSourceEdmSchemaNotValidError() }; } using (TempFileCollection collection = new TempFileCollection()) { string tempSourceEdmSchemaPath = collection.AddExtension(XmlConstants.CSpaceSchemaExtension); SaveXmlReaderToFile(sourceEdmSchema, tempSourceEdmSchemaPath); return InternalGenerateCode(tempSourceEdmSchemaPath, schemaVersion, new LazyTextWriterCreator(target), null, targetEntityFrameworkVersion); } } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Edm")] [ResourceConsumption(ResourceScope.Machine)] // temp file creation, and passing to InternalGenerateCode public IList GenerateCode(XmlReader sourceEdmSchema, TextWriter target) { Version targetFrameworkVersion; IList errors = GetMinimumTargetFrameworkVersion(sourceEdmSchema, out targetFrameworkVersion); if (errors.Where(e => e.Severity == EdmSchemaErrorSeverity.Error).Any()) { return errors; } return errors.Concat(GenerateCode(sourceEdmSchema, target, targetFrameworkVersion)).ToList(); } /// /// Creates a source code file that contains the object layer code generated from the specified conceptual schema /// definition language (CSDL) file. Note that the targetEntityFrameworkVersion parameter uses internal Entity /// Framework version numbers as described in the class. /// /// An XmlReader that contains the CSDL. /// The TextWriter to which the object layer code is written. /// /// A list of XmlReader objects that contain schemas that are referenced by the source schema (the CSDL). /// If the source schema does not have any dependencies, pass in an empty IList object. /// /// The internal Entity Framework version that is being targeted. /// A list of objects that contains any generated errors. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Edm")] [ResourceConsumption(ResourceScope.Machine)] //Temp file creation, and passing to InternalGenerateCode public IList GenerateCode(XmlReader sourceEdmSchema, TextWriter target, IEnumerable additionalEdmSchemas, Version targetEntityFrameworkVersion) { EDesignUtil.CheckArgumentNull(sourceEdmSchema, "sourceEdmSchema"); EDesignUtil.CheckArgumentNull(additionalEdmSchemas, "additionalEdmSchemas"); EDesignUtil.CheckArgumentNull(target, "target"); EDesignUtil.CheckTargetEntityFrameworkVersionArgument(targetEntityFrameworkVersion, "targetEntityFrameworkVersion"); Version schemaVersion; if (!IsValidSchema(sourceEdmSchema, out schemaVersion)) { return new List() { CreateSourceEdmSchemaNotValidError() }; } using (TempFileCollection collection = new TempFileCollection()) { string tempSourceEdmSchemaPath = collection.AddExtension(XmlConstants.CSpaceSchemaExtension); SaveXmlReaderToFile(sourceEdmSchema, tempSourceEdmSchemaPath); List additionalTempPaths = new List(); foreach (XmlReader reader in additionalEdmSchemas) { string temp = Path.GetTempFileName() + XmlConstants.CSpaceSchemaExtension; SaveXmlReaderToFile(reader, temp); additionalTempPaths.Add(temp); collection.AddFile(temp, false); } return InternalGenerateCode(tempSourceEdmSchemaPath, schemaVersion, new LazyTextWriterCreator(target), additionalTempPaths, targetEntityFrameworkVersion); } } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Edm")] [ResourceConsumption(ResourceScope.Machine)] //Temp file creation, and passing to InternalGenerateCode public IList GenerateCode(XmlReader sourceEdmSchema, TextWriter target, IEnumerable additionalEdmSchemas) { Version targetFrameworkVersion; IList errors = GetMinimumTargetFrameworkVersion(sourceEdmSchema, out targetFrameworkVersion); if (errors.Where(e => e.Severity == EdmSchemaErrorSeverity.Error).Any()) { return errors; } return errors.Concat(GenerateCode(sourceEdmSchema, target, additionalEdmSchemas, targetFrameworkVersion)).ToList(); } // this overload is for entry points that don't pass in readers, so we need to actually create a reader to get the schemaVersion out private IList InternalGenerateCode(string sourceEdmSchemaFilePath, LazyTextWriterCreator textWriter, IEnumerable additionalEdmSchemaFilePaths, Version targetFrameworkVersion) { // do this check to maintain backwards compatibility with the behavior shipped in // framework v4 if (!File.Exists(sourceEdmSchemaFilePath)) { return new List() { new EdmSchemaError(Strings.EdmSchemaFileNotFound(sourceEdmSchemaFilePath), (int)ModelBuilderErrorCode.FileNotFound, EdmSchemaErrorSeverity.Error, sourceEdmSchemaFilePath, 0, 0) }; } using (XmlReader reader = XmlReader.Create(sourceEdmSchemaFilePath)) { Version schemaVersion; if (!IsValidSchema(reader, out schemaVersion)) { return new List() { CreateSourceEdmSchemaNotValidError() }; } return InternalGenerateCode(sourceEdmSchemaFilePath, schemaVersion, textWriter, additionalEdmSchemaFilePaths, targetFrameworkVersion); } } private bool IsValidSchema(XmlReader reader, out Version entityFrameworkVersion) { double schemaVersion; DataSpace dataSpace; if (System.Data.EntityModel.SchemaObjectModel.SchemaManager.TryGetSchemaVersion(reader, out schemaVersion, out dataSpace) && dataSpace == DataSpace.CSpace) { entityFrameworkVersion = EntityFrameworkVersionsUtil.ConvertToVersion(schemaVersion); return true; } else if (EntityFrameworkVersions.TryGetEdmxVersion(reader, out entityFrameworkVersion)) { return true; } return false; } private IList GetMinimumTargetFrameworkVersion(string sourceEdmSchemaFilePath, out Version targetFrameworkVersion) { targetFrameworkVersion = null; try { using (XmlReader reader = XmlReader.Create(sourceEdmSchemaFilePath)) { return GetMinimumTargetFrameworkVersion(reader, out targetFrameworkVersion); } } catch (System.IO.FileNotFoundException ex) { return new List() { EntityClassGenerator.CreateErrorForException(ModelBuilderErrorCode.FileNotFound, ex) }; } } private IList GetMinimumTargetFrameworkVersion(XmlReader sourceEdmSchemaXmlReader, out Version targetFrameworkVersion) { List errorList = new List(); if (!IsValidSchema(sourceEdmSchemaXmlReader, out targetFrameworkVersion)) { errorList.Add(CreateSourceEdmSchemaNotValidError()); return errorList; } if (targetFrameworkVersion < EntityFrameworkVersions.Version2) { targetFrameworkVersion = EntityFrameworkVersions.Version2; } if (targetFrameworkVersion > EntityFrameworkVersions.Default) { errorList.Add(new EdmSchemaError(Strings.DefaultTargetVersionTooLow(EntityFrameworkVersions.Default, targetFrameworkVersion), (int)ModelBuilderErrorCode.SchemaVersionHigherThanTargetVersion, EdmSchemaErrorSeverity.Warning)); } return errorList; } private IList InternalGenerateCode(string sourceEdmSchemaFilePath, Version schemaVersion, LazyTextWriterCreator textWriter, IEnumerable additionalEdmSchemaFilePaths, Version targetFrameworkVersion) { List errors = new List(); try { if (targetFrameworkVersion == EntityFrameworkVersions.Version1) { errors.Add(new EdmSchemaError(Strings.EntityCodeGenTargetTooLow, (int)ModelBuilderErrorCode.TargetVersionNotSupported, EdmSchemaErrorSeverity.Error)); return errors; } if (!MetadataItemCollectionFactory.ValidateActualVersionAgainstTarget(targetFrameworkVersion, schemaVersion, errors)) { return errors; } if (schemaVersion == EntityFrameworkVersions.EdmVersion1_1) { return GenerateCodeFor1_1Schema(sourceEdmSchemaFilePath, textWriter, additionalEdmSchemaFilePaths); } ReflectionAdapter codeGenerator = ReflectionAdapter.Create(_languageOption, targetFrameworkVersion); codeGenerator.SourceCsdlPath = sourceEdmSchemaFilePath; codeGenerator.ReferenceCsdlPaths = additionalEdmSchemaFilePaths; codeGenerator.EdmToObjectNamespaceMap = _edmToObjectNamespaceMap.AsDictionary(); string code = codeGenerator.TransformText(); if (codeGenerator.Errors.Count != 0) { ModelBuilderErrorCode errorCode = ModelBuilderErrorCode.PreprocessTemplateTransformationError; errors.AddRange(codeGenerator.Errors.OfType().Select(c => ConvertToEdmSchemaError(c, errorCode))); if (codeGenerator.Errors.HasErrors) return errors; } using (TextWriter writer = textWriter.GetOrCreateTextWriter()) { writer.Write(code); } } catch (System.UnauthorizedAccessException ex) { errors.Add(EntityClassGenerator.CreateErrorForException(ModelBuilderErrorCode.SecurityError, ex)); } catch (System.IO.FileNotFoundException ex) { errors.Add(EntityClassGenerator.CreateErrorForException(ModelBuilderErrorCode.FileNotFound, ex)); } catch (System.Security.SecurityException ex) { errors.Add(EntityClassGenerator.CreateErrorForException(ModelBuilderErrorCode.SecurityError, ex)); } catch (System.IO.DirectoryNotFoundException ex) { errors.Add(EntityClassGenerator.CreateErrorForException(ModelBuilderErrorCode.DirectoryNotFound, ex)); } catch (System.IO.IOException ex) { errors.Add(EntityClassGenerator.CreateErrorForException(ModelBuilderErrorCode.IOException, ex)); } catch (Exception e) { if (MetadataUtil.IsCatchableExceptionType(e)) { errors.Add(EntityClassGenerator.CreateErrorForException(ModelBuilderErrorCode.PreprocessTemplateTransformationError, e, sourceEdmSchemaFilePath)); } else { throw; } } return errors; } private static EdmSchemaError CreateSourceEdmSchemaNotValidError() { return new EdmSchemaError(Strings.EdmSchemaNotValid, (int)ModelBuilderErrorCode.SourceSchemaIsInvalid, EdmSchemaErrorSeverity.Error); } private IList GenerateCodeFor1_1Schema(string sourceEdmSchemaFilePath, LazyTextWriterCreator textWriter, IEnumerable additionalEdmSchemaFilePaths) { EntityClassGenerator generator = new EntityClassGenerator(_languageOption); string target = textWriter.TargetFilePath; bool cleanUpTarget = false; try { if (textWriter.IsUserSuppliedTextWriter) { cleanUpTarget = true; target = Path.Combine(Path.GetTempPath(), Path.GetTempFileName()); } IList errors = generator.GenerateCode(sourceEdmSchemaFilePath, target, additionalEdmSchemaFilePaths != null ? additionalEdmSchemaFilePaths : Enumerable.Empty()); if (textWriter.IsUserSuppliedTextWriter && !errors.Any(e => e.Severity == EdmSchemaErrorSeverity.Error)) { textWriter.GetOrCreateTextWriter().Write(File.ReadAllText(target)); } return errors; } finally { if (cleanUpTarget && target != null && File.Exists(target)) { File.Delete(target); } } } private static void SaveXmlReaderToFile(XmlReader schema, string tempSchemaPath) { using (XmlWriter writer = XmlWriter.Create(tempSchemaPath)) { writer.WriteNode(schema, false); } } private static EdmSchemaError ConvertToEdmSchemaError(CompilerError error, ModelBuilderErrorCode defaultErrorCode) { int errorNumber; string message = error.ErrorText; bool usePositionInfo = true; EdmSchemaErrorSeverity severity = error.IsWarning ? EdmSchemaErrorSeverity.Warning : EdmSchemaErrorSeverity.Error; if (int.TryParse(error.ErrorNumber, out errorNumber)) { if (error.Line == -1 && error.Column == -1) { usePositionInfo = false; } } else { message = String.Format(CultureInfo.InvariantCulture, "{0}({1})", error.ErrorText, error.ErrorNumber); errorNumber = (int)defaultErrorCode; } if (usePositionInfo) { return new EdmSchemaError(message, errorNumber, severity, error.FileName, error.Line, error.Column); } else { return new EdmSchemaError(message, errorNumber, severity); } } static Type _vbCodeGeneratorTypeV2 = null; static Type _vbCodeGeneratorTypeV3 = null; static Type _csharpCodeGeneratorTypeV2 = null; static Type _csharpCodeGeneratorTypeV3 = null; private const string CSharpTemplateCodeGenTypeName = "TemplateCodeGenerators.CSharpCodeGenTemplate"; private const string VBTemplateCodeGenTypeName = "TemplateCodeGenerators.VBCodeGenTemplate"; private const string CSharpTemplateCodeGenV3TypeName = CSharpTemplateCodeGenTypeName + "V50"; private const string VBTemplateCodeGenV3TypeName = VBTemplateCodeGenTypeName + "V50"; private const string CSharpTemplateCodeGenResourceV2 = CSharpTemplateCodeGenTypeName + ".cs"; private const string CSharpTemplateCodeGenResourceV3 = CSharpTemplateCodeGenTypeName + "V5.0.cs"; private const string VBTemplateCodeGenResourceV2 = VBTemplateCodeGenTypeName + ".vb"; private const string VBTemplateCodeGenResourceV3 = VBTemplateCodeGenTypeName + "V5.0.vb"; private static object CreateCSharpCodeGeneratorV2() { if (_csharpCodeGeneratorTypeV2 == null) { Type type = CreateCodeGeneratorType(new Microsoft.CSharp.CSharpCodeProvider(), CSharpTemplateCodeGenResourceV2, CSharpTemplateCodeGenTypeName); Interlocked.Exchange(ref _csharpCodeGeneratorTypeV2, type); } return Activator.CreateInstance(_csharpCodeGeneratorTypeV2); } private static object CreateCSharpCodeGeneratorV3() { if (_csharpCodeGeneratorTypeV3 == null) { Type type = CreateCodeGeneratorType(new Microsoft.CSharp.CSharpCodeProvider(), CSharpTemplateCodeGenResourceV3, CSharpTemplateCodeGenV3TypeName); Interlocked.Exchange(ref _csharpCodeGeneratorTypeV3, type); } return Activator.CreateInstance(_csharpCodeGeneratorTypeV3); } private static object CreateVBCodeGeneratorV2() { if (_vbCodeGeneratorTypeV2 == null) { Type type = CreateCodeGeneratorType(new Microsoft.VisualBasic.VBCodeProvider(), VBTemplateCodeGenResourceV2, VBTemplateCodeGenTypeName); Interlocked.Exchange(ref _vbCodeGeneratorTypeV2, type); } return Activator.CreateInstance(_vbCodeGeneratorTypeV2); } private static object CreateVBCodeGeneratorV3() { if (_vbCodeGeneratorTypeV3 == null) { Type type = CreateCodeGeneratorType(new Microsoft.VisualBasic.VBCodeProvider(), VBTemplateCodeGenResourceV3, VBTemplateCodeGenV3TypeName); Interlocked.Exchange(ref _vbCodeGeneratorTypeV3, type); } return Activator.CreateInstance(_vbCodeGeneratorTypeV3); } private static Type CreateCodeGeneratorType(System.CodeDom.Compiler.CodeDomProvider compilerProvider, string resourceName, string typeName) { string sourceCode = null; using (Stream sourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName)) using (StreamReader reader = new StreamReader(sourceStream)) { sourceCode = reader.ReadToEnd(); } CompilerParameters compilerParams = new CompilerParameters(); compilerParams.CompilerOptions = "/d:PREPROCESSED_TEMPLATE"; compilerParams.GenerateInMemory = true; compilerParams.GenerateExecutable = false; // grab the assemblies by location so that we don't compile against one that we didn't reference compilerParams.ReferencedAssemblies.AddRange(new string[] { typeof(System.CodeDom.Compiler.CodeDomProvider).Assembly.Location, // System.dll typeof(System.Linq.Enumerable).Assembly.Location, // System.Core.dll typeof(System.Data.Objects.ObjectContext).Assembly.Location, // System.Data.Entity.dll typeof(System.Data.Entity.Design.EntityCodeGenerator).Assembly.Location, // System.Data.Entity.Design.dll typeof(System.Data.DbType).Assembly.Location, // System.Data.dll typeof(System.Xml.XmlAttribute).Assembly.Location, // System.Xml.dll typeof(System.Xml.Linq.XElement).Assembly.Location, // System.Xml.Linq.dll }); #if !ENABLE_TEMPLATE_DEBUGGING CompilerResults results = compilerProvider.CompileAssemblyFromSource(compilerParams, sourceCode); #else // enables debugging compilerParams.GenerateInMemory = false; compilerParams.IncludeDebugInformation = true; string baseName = Path.GetFileNameWithoutExtension(Path.GetTempFileName()) + "."; compilerParams.OutputAssembly = Path.Combine(Path.GetTempPath(), baseName + typeName + ".Assembly.dll"); string sourceFileName = Path.Combine(Path.GetTempPath(), baseName + typeName + ".Source." + compilerProvider.FileExtension); File.WriteAllText(sourceFileName, sourceCode); CompilerResults results = compilerProvider.CompileAssemblyFromFile(compilerParams, sourceFileName); #warning DO NOT CHECK IN LIKE THIS, Dynamic Assembly Debugging is enabled #endif if (results.Errors.HasErrors) { string message = results.Errors.OfType().Aggregate(string.Empty, (accumulated, input) => accumulated == string.Empty ? input.ToString() : accumulated + Environment.NewLine + input.ToString()); throw EDesignUtil.InvalidOperation(message); } return results.CompiledAssembly.GetType(typeName); } private class ReflectionAdapter { private object _instance; private MethodInfo _transformText; private PropertyInfo _sourceCsdlPath; private PropertyInfo _referenceCsdlPaths; private PropertyInfo _errors; private PropertyInfo _edmToObjectNamespaceMap; internal ReflectionAdapter(object instance) { _instance = instance; Type type = _instance.GetType(); BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy; _transformText = type.GetMethod("TransformText", flags, null, new Type[0], null); Debug.Assert(_transformText != null, "Unable to find method, did the signature or name change?"); _sourceCsdlPath = type.GetProperty("SourceCsdlPath", flags, null, typeof(String), new Type[0], null); Debug.Assert(_sourceCsdlPath != null, "Unable to find property, did the signature or name change?"); _referenceCsdlPaths = type.GetProperty("ReferenceCsdlPaths", flags, null, typeof(IEnumerable), new Type[0], null); Debug.Assert(_referenceCsdlPaths != null, "Unable to find property, did the signature or name change?"); _errors = type.GetProperty("Errors", flags, null, typeof(CompilerErrorCollection), new Type[0], null); Debug.Assert(_errors != null, "Unable to find property, did the signature or name change?"); _edmToObjectNamespaceMap = type.GetProperty("EdmToObjectNamespaceMap", flags, null, typeof(Dictionary), new Type[0], null); Debug.Assert(_edmToObjectNamespaceMap != null, "Unable to find property, did the signature or name change?"); } internal CompilerErrorCollection Errors { get { return (CompilerErrorCollection)_errors.GetValue(_instance, null); } } internal IEnumerable ReferenceCsdlPaths { set { _referenceCsdlPaths.SetValue(_instance, value, null); } } internal string SourceCsdlPath { get { return (String)_sourceCsdlPath.GetValue(_instance, null); } set { _sourceCsdlPath.SetValue(_instance, value, null); } } internal Dictionary EdmToObjectNamespaceMap { set { _edmToObjectNamespaceMap.SetValue(_instance, value, null); } } internal string TransformText() { try { return (string)_transformText.Invoke(_instance, new object[0]); } catch (TargetInvocationException e) { Exception actual = e.InnerException != null ? e.InnerException : e; System.CodeDom.Compiler.CompilerError error = new System.CodeDom.Compiler.CompilerError(); error.ErrorText = actual.Message; error.IsWarning = false; error.FileName = SourceCsdlPath; Errors.Add(error); return string.Empty; } } internal static ReflectionAdapter Create(LanguageOption language, Version targetEntityFrameworkVersion) { if (language == LanguageOption.GenerateCSharpCode) { if (targetEntityFrameworkVersion >= EntityFrameworkVersions.Latest) { return new ReflectionAdapter(CreateCSharpCodeGeneratorV3()); } else { return new ReflectionAdapter(CreateCSharpCodeGeneratorV2()); } } else { Debug.Assert(language == LanguageOption.GenerateVBCode, "Did you add a new option?"); if (targetEntityFrameworkVersion >= EntityFrameworkVersions.Latest) { return new ReflectionAdapter(CreateVBCodeGeneratorV3()); } else { return new ReflectionAdapter(CreateVBCodeGeneratorV2()); } } } } } }