/// <summary>
        /// This method will return type given by the dataTypeDescriptor.
        /// If the data type does not exist, one will be dynamically
        /// runtime code generated.
        /// </summary>
        /// <param name="dataTypeDescriptor"></param>
        /// <param name="forceReCompilation">If this is true a new type will be compiled regardless if one already exists.</param>
        /// <returns></returns>
        public static Type GetType(DataTypeDescriptor dataTypeDescriptor, bool forceReCompilation = false)
        {
            bool codeGenerationNeeded;

            Type type = TryGetType(dataTypeDescriptor, forceReCompilation, out codeGenerationNeeded);
            if (type != null)
            {
                return type;
            }

            if (codeGenerationNeeded)
            {
                lock (_lock)
                {
                    type = TypeManager.TryGetType(dataTypeDescriptor.GetFullInterfaceName());
                    if (type != null) return type;

                    var codeGenerationBuilder = new CodeGenerationBuilder("DataInterface: " + dataTypeDescriptor.Name);
                    InterfaceCodeGenerator.AddAssemblyReferences(codeGenerationBuilder, dataTypeDescriptor);
                    InterfaceCodeGenerator.AddInterfaceTypeCode(codeGenerationBuilder, dataTypeDescriptor);

                    IEnumerable<Type> types = CodeGenerationManager.CompileRuntimeTempTypes(codeGenerationBuilder);

                    return types.Single();
                }
            }

            return null;
        }
        private static void Compile(CodeGenerationBuilder builder)
        {
            var compilerParameters = new CompilerParameters
            {
                GenerateExecutable = false,
                GenerateInMemory   = false,
                OutputAssembly     = CompositeGeneratedAssemblyPath,
                TempFiles          = new TempFileCollection(TempAssemblyFolderPath)
            };

            compilerParameters.ReferencedAssemblies.AddRangeIfNotContained(builder.AssemblyLocations.ToArray());
            compilerParameters.AddAssemblyLocationsFromBin();

            var codeCompileUnit = new CodeCompileUnit();

            codeCompileUnit.Namespaces.AddRange(builder.Namespaces.ToArray());


            for (int i = 0; i < NumberOfCompileRetries; i++)
            {
                var             compiler      = new CSharpCodeProvider();
                CompilerResults compileResult = compiler.CompileAssemblyFromDom(compilerParameters, codeCompileUnit);


                if (compileResult.Errors.Count == 0)
                {
                    return;
                }

                if (i == NumberOfCompileRetries - 1)
                {
#if OUTPUT_SOURCE_CODE_ON_ERROR
                    using (FileStream file = File.Create(Path.Combine(PathUtil.BaseDirectory, "output.cs")))
                    {
                        using (var sw = new StreamWriter(file))
                        {
                            compiler.GenerateCodeFromCompileUnit(codeCompileUnit, sw, new CodeGeneratorOptions());
                        }
                    }
#endif

                    var sb = new StringBuilder();
                    foreach (CompilerError compilerError in compileResult.Errors)
                    {
                        if (compilerError.IsWarning)
                        {
                            continue;
                        }

                        string entry = "Compile error: " + compilerError.ErrorNumber + "(" + compilerError.Line + ")" + ": " + compilerError.ErrorText.Replace("{", "{{").Replace("}", "}}");

                        Log.LogError(LogTitle, entry);

                        sb.AppendLine(entry);
                    }

                    throw new InvalidOperationException(sb.ToString());
                }
            }
        }
 /// <summary>
 /// Adds the assembly references required by the supplied <see cref="DataTypeDescriptor"/> to the supplied  <see cref="CodeGenerationBuilder"/>
 /// </summary>
 /// <param name="codeGenerationBuilder">Assembly refences is added to this builder</param>
 /// <param name="dataTypeDescriptor">Data type descriptor which may contain references to assemblies</param>
 public static void AddAssemblyReferences(CodeGenerationBuilder codeGenerationBuilder, DataTypeDescriptor dataTypeDescriptor)
 {
     foreach (Assembly assembly in GetReferencedAssemblies(dataTypeDescriptor))
     {
         codeGenerationBuilder.AddReference(assembly);
     }
 }
 private static void PopulateBuilder(CodeGenerationBuilder builder)
 {
     foreach (ICodeProvider provider in CodeProviders)
     {
         provider.GetCodeToCompile(builder);
     }
 }
 public void GetCodeToCompile(CodeGenerationBuilder builder)
 {
     foreach (DataTypeDescriptor dataTypeDescriptor in DataMetaDataFacade.GeneratedTypeDataTypeDescriptors)
     {
         InterfaceCodeGenerator.AddAssemblyReferences(builder, dataTypeDescriptor);
         InterfaceCodeGenerator.AddInterfaceTypeCode(builder, dataTypeDescriptor);                
     }
 }
        internal static void AddDataWrapperClassCode(CodeGenerationBuilder codeGenerationBuilder, Type interfaceType)
        {
            codeGenerationBuilder.AddReference(interfaceType.Assembly);

            DataTypeDescriptor dataTypeDescriptor = ReflectionBasedDescriptorBuilder.Build(interfaceType);

            AddDataWrapperClassCode(codeGenerationBuilder, dataTypeDescriptor);
        }
        /// <summary>
        /// Adds the source code defined by <see cref="DataTypeDescriptor"/> to the supplied  <see cref="CodeGenerationBuilder"/>
        /// </summary>
        /// <param name="codeGenerationBuilder">Source code is added to this builder</param>
        /// <param name="dataTypeDescriptor">Data type descriptor to convert into source code</param>
        public static void AddInterfaceTypeCode(CodeGenerationBuilder codeGenerationBuilder, DataTypeDescriptor dataTypeDescriptor)
        {
            var codeTypeDeclaration = CreateCodeTypeDeclaration(dataTypeDescriptor);

            var codeNamespace = new CodeNamespace(dataTypeDescriptor.Namespace);
            codeNamespace.Types.Add(codeTypeDeclaration);
            codeGenerationBuilder.AddNamespace(codeNamespace);
        }
        public XmlDataProviderCodeBuilder(string providerName, CodeGenerationBuilder codeGenerationBuilder)
        {
            _codeGenerationBuilder = codeGenerationBuilder;

            _namespaceName = NamesCreator.MakeNamespaceName(providerName);

            AddCodeNamespaces();
        }
        internal static void AddPropertySerializerTypeCode(CodeGenerationBuilder codeGenerationBuilder, string propertyClassTypeName, IList<Tuple<string, Type>> properties)
        {
            codeGenerationBuilder.AddReference(typeof(EditorBrowsableAttribute).Assembly);
            codeGenerationBuilder.AddReference(typeof(StringConversionServices).Assembly);

            CodeTypeDeclaration codeTypeDeclaration = CreateCodeTypeDeclaration(propertyClassTypeName, properties);

            codeGenerationBuilder.AddType(NamespaceName, codeTypeDeclaration);
        }
        private static Type CodeGeneratePropertySerializer(Type propertyClassType)
        {
            CodeGenerationBuilder codeGenerationBuilder = new CodeGenerationBuilder("PropertySerializer: " + propertyClassType.FullName);

            PropertySerializerTypeCodeGenerator.AddPropertySerializerTypeCode(codeGenerationBuilder, propertyClassType);

            IEnumerable<Type> types = CodeGenerationManager.CompileRuntimeTempTypes(codeGenerationBuilder);

            return types.Single();
        }
        internal static void AddEmptyDataClassTypeCode(CodeGenerationBuilder codeGenerationBuilder, DataTypeDescriptor dataTypeDescriptor, Type baseClassType = null, CodeAttributeDeclaration codeAttributeDeclaration = null)
        {
            Type interfaceType = DataTypeTypesManager.GetDataType(dataTypeDescriptor);
            if (interfaceType == null) return;

            if (baseClassType == null) baseClassType = typeof(EmptyDataClassBase);

            CodeTypeDeclaration codeTypeDeclaration = CreateCodeTypeDeclaration(dataTypeDescriptor, baseClassType, codeAttributeDeclaration);

            codeGenerationBuilder.AddType(NamespaceName, codeTypeDeclaration);
        }
        internal static void AddDataWrapperClassCode(CodeGenerationBuilder codeGenerationBuilder, DataTypeDescriptor dataTypeDescriptor)
        {
            Type interfaceType = DataTypeTypesManager.GetDataType(dataTypeDescriptor);
            if (interfaceType == null) return;

            codeGenerationBuilder.AddReference(typeof(IDataWrapper).Assembly);
            codeGenerationBuilder.AddReference(typeof(EditorBrowsableAttribute).Assembly);

            CodeTypeDeclaration codeTypeDeclaration = CreateCodeTypeDeclaration(dataTypeDescriptor);

            codeGenerationBuilder.AddType(NamespaceName, codeTypeDeclaration);
        }
        public void GetCodeToCompile(CodeGenerationBuilder builder)
        {
            foreach (DataTypeDescriptor dataTypeDescriptor in DataMetaDataFacade.AllDataTypeDescriptors)
            {
                if (!dataTypeDescriptor.ValidateRuntimeType())
                {
                    Log.LogError("DataWrapperClassCodeProvider", string.Format("The non code generated interface type '{0}' was not found, skipping code generation for that type", dataTypeDescriptor));
                    continue;
                }

                DataWrapperCodeGenerator.AddDataWrapperClassCode(builder, dataTypeDescriptor);
            }
        }
        private static void Compile(CodeGenerationBuilder builder)
        {
            var compilerParameters = new CompilerParameters
            {
                GenerateExecutable = false,
                GenerateInMemory   = false,
                OutputAssembly     = CompositeGeneratedAssemblyPath,
                TempFiles          = new TempFileCollection(TempAssemblyFolderPath)
            };

            compilerParameters.ReferencedAssemblies.AddRangeIfNotContained(builder.AssemblyLocations.ToArray());
            compilerParameters.AddAssemblyLocationsFromBin();

            var codeCompileUnit = new CodeCompileUnit();

            codeCompileUnit.Namespaces.AddRange(builder.Namespaces.ToArray());

            for (var i = 0; i < NumberOfCompileRetries; i++)
            {
                var             compiler      = CSharpCodeProviderFactory.CreateCompiler();
                CompilerResults compileResult = compiler.CompileAssemblyFromDom(compilerParameters, codeCompileUnit);

                if (!compileResult.Errors.HasErrors)
                {
                    return;
                }

                if (i == NumberOfCompileRetries - 1)
                {
                    OutputSourceCodeOnError(compiler, codeCompileUnit);

                    var sb = new StringBuilder();
                    foreach (CompilerError compilerError in compileResult.Errors)
                    {
                        if (compilerError.IsWarning)
                        {
                            continue;
                        }

                        var entry = "Compile error: " + compilerError.ErrorNumber + "(" + compilerError.Line + ")" + ": " + compilerError.ErrorText.Replace("{", "{{").Replace("}", "}}");

                        Log.LogError(LogTitle, entry);

                        sb.AppendLine(entry);
                    }

                    throw new InvalidOperationException(sb.ToString());
                }
            }
        }
        internal static void AddAssemblyReferences(CodeGenerationBuilder codeGenerationBuilder, DataTypeDescriptor dataTypeDescriptor)
        {
            Type interfaceType = DataTypeTypesManager.GetDataType(dataTypeDescriptor);
            if (interfaceType == null) return;

            codeGenerationBuilder.AddReference(typeof(EmptyDataClassBase).Assembly);
            codeGenerationBuilder.AddReference(typeof(EditorBrowsableAttribute).Assembly);
            codeGenerationBuilder.AddReference(interfaceType.Assembly);

            if (!string.IsNullOrEmpty(dataTypeDescriptor.BuildNewHandlerTypeName))
            {
                Type buildeNewHandlerType = TypeManager.GetType(dataTypeDescriptor.BuildNewHandlerTypeName);
                codeGenerationBuilder.AddReference(buildeNewHandlerType.Assembly);
            }
        }
        public void GetCodeToCompile(CodeGenerationBuilder builder)
        {
            foreach (DataTypeDescriptor dataTypeDescriptor in DataMetaDataFacade.AllDataTypeDescriptors)
            {
                if (!dataTypeDescriptor.ValidateRuntimeType())
                {
                    Log.LogError("EmptyDataClassCodeProvider", "The non code generated interface type '{0}' was not found, skipping code generation for that type", dataTypeDescriptor);
                    continue;
                }

                if (string.IsNullOrEmpty(dataTypeDescriptor.BuildNewHandlerTypeName))
                {
                    EmptyDataClassCodeGenerator.AddAssemblyReferences(builder, dataTypeDescriptor);
                    EmptyDataClassCodeGenerator.AddEmptyDataClassTypeCode(builder, dataTypeDescriptor);
                }
            }
        }
Beispiel #17
0
        public static Type GetDataWrapperType(Type interfaceType)
        {
            Type wrapperType = TryGetWrapperType(interfaceType.FullName);
            if (wrapperType != null) return wrapperType;

            lock (_lock)
            {
                wrapperType = TryGetWrapperType(interfaceType.FullName);
                if (wrapperType != null) return wrapperType;

                var codeGenerationBuilder = new CodeGenerationBuilder("DataWrapper:" + interfaceType.FullName);

                DataWrapperCodeGenerator.AddDataWrapperClassCode(codeGenerationBuilder, interfaceType);

                IEnumerable<Type> types = CodeGenerationManager.CompileRuntimeTempTypes(codeGenerationBuilder);

                return types.Single();
            }
        }
Beispiel #18
0
        public static Type GetDataWrapperType(DataTypeDescriptor dataTypeDescriptor)
        {
            Type wrapperType = TryGetWrapperType(dataTypeDescriptor.GetFullInterfaceName());
            if (wrapperType != null) return wrapperType;

            lock (_lock)
            {
                wrapperType = TryGetWrapperType(dataTypeDescriptor.GetFullInterfaceName());
                if (wrapperType != null) return wrapperType;

                var codeGenerationBuilder = new CodeGenerationBuilder("DataWrapper:" + dataTypeDescriptor.GetFullInterfaceName());

                DataWrapperCodeGenerator.AddDataWrapperClassCode(codeGenerationBuilder, dataTypeDescriptor);

                IEnumerable<Type> types = CodeGenerationManager.CompileRuntimeTempTypes(codeGenerationBuilder);

                return types.Single();
            }
        }
        /// <summary>
        /// This method will recompile Composite.Generated.dll and drop it into bin.
        /// </summary>
        /// <param name="forceGeneration"></param>
        public static void GenerateCompositeGeneratedAssembly(bool forceGeneration = false)
        {
            if (SuppressGeneration)
            {
                return;
            }

            if (forceGeneration || !_compositeGeneratedCompiled)
            {
                lock (_lock)
                {
                    if (forceGeneration || !_compositeGeneratedCompiled)
                    {
                        Log.LogVerbose(LogTitle, $"Compiling new assembly in this application domain ({AppDomain.CurrentDomain.Id})");

                        int t1 = Environment.TickCount;

                        var builder = new CodeGenerationBuilder("Composite.Generated.dll");
                        PopulateBuilder(builder);

                        int t2 = Environment.TickCount;

                        Compile(builder);

                        int t3 = Environment.TickCount;

                        int numberOfTypes = builder.Namespaces.SelectMany(f => f.Types.OfType <CodeTypeDeclaration>()).Count();

                        Log.LogVerbose(LogTitle, "Number of types build: " + numberOfTypes +
                                       "\nBuilding code dom: " + (t2 - t1) + "ms" +
                                       "\nCompiling code dom: " + (t3 - t2) + "ms" +
                                       "\nTotal compilation: " + (t3 - t1) + "ms");

                        _compositeGeneratedCompiled = true;

                        return;
                    }
                }
            }

            Log.LogVerbose(LogTitle, "New assembly already compiled by this application domain ({0})", AppDomain.CurrentDomain.Id);
        }
        /// <summary>
        /// This method will compile the type defined in <paramref name="codeGenerationBuilder"/>
        /// and return the result types. These types exists in a temp assembly, that will be
        /// deleted when the app domain is terminated.
        /// </summary>
        /// <param name="codeGenerationBuilder"></param>
        /// <param name="verbose"></param>
        /// <returns></returns>
        public static IEnumerable<Type> CompileRuntimeTempTypes(CodeGenerationBuilder codeGenerationBuilder, bool verbose = true)
        {
            int t1 = Environment.TickCount;

            _compositeGeneratedCompiled = false; // When compiling a new type, Composite.Generated.dll should always be recompiled

            var compilerParameters = new CompilerParameters
            {
                GenerateExecutable = false,
                GenerateInMemory = false,
                OutputAssembly = Path.Combine(TempAssemblyFolderPath, Guid.NewGuid() + ".dll")
            };

            compilerParameters.ReferencedAssemblies.AddRangeIfNotContained(codeGenerationBuilder.AssemblyLocations.ToArray());
            compilerParameters.ReferencedAssemblies.AddRangeIfNotContained(_compiledAssemblies.Select(f => f.Location).ToArray());
            compilerParameters.AddAssemblyLocationsFromBin();


            var codeCompileUnit = new CodeCompileUnit();
            codeCompileUnit.Namespaces.AddRange(codeGenerationBuilder.Namespaces.ToArray());

            var compiler = new CSharpCodeProvider();
            var compileResult = compiler.CompileAssemblyFromDom(compilerParameters, codeCompileUnit);

            if (compileResult.Errors.Count == 0)
            {
                Assembly resultAssembly = compileResult.CompiledAssembly;

                AddCompiledAssembly(resultAssembly);

                Type[] resultTypes = resultAssembly.GetTypes();

                int t2 = Environment.TickCount;

                Log.LogVerbose(LogTitle, string.Format("Compile '{0}' in {1}ms", codeGenerationBuilder.DebugLabel, t2 - t1));
                Log.LogVerbose(LogTitle, string.Format("Types from : {0}", compilerParameters.OutputAssembly));

                foreach (Type resultType in resultTypes)
                {
                    _compiledTypesByFullName[resultType.FullName] = resultType;
                }

                return resultTypes;
            }


#if OUTPUT_SOURCE_CODE_ON_ERROR
            using (FileStream file = File.Create(Path.Combine(PathUtil.BaseDirectory, "output.cs")))
            {
                using (var sw = new StreamWriter(file))
                {
                    compiler.GenerateCodeFromCompileUnit(codeCompileUnit, sw, new CodeGeneratorOptions());
                }
            }
#endif

            var failedAssemblyLoads = new List<Pair<string, Exception>>();
            foreach (string assemblyLocation in compilerParameters.ReferencedAssemblies)
            {
                try
                {
                    Assembly assembly = Assembly.LoadFrom(assemblyLocation);
                    var types = assembly.GetTypes(); // Accessing GetTypes() to iterate classes
                }
                catch (Exception ex)
                {
                    Exception exceptionToLog = ex;

                    var loadException = ex as ReflectionTypeLoadException;
                    if (loadException != null 
                        && loadException.LoaderExceptions != null
                        && loadException.LoaderExceptions.Any())
                    {
                        exceptionToLog = loadException.LoaderExceptions.First();
                    }

                    failedAssemblyLoads.Add(new Pair<string, Exception>( assemblyLocation, exceptionToLog));
                }
            }


            var sb = new StringBuilder();
            failedAssemblyLoads.ForEach(asm => sb.AppendFormat("Failed to load dll: '{0}' : {1}", asm.First, asm.Second).AppendLine());

            sb.AppendLine("Failed building: " + codeGenerationBuilder.DebugLabel);
            foreach (CompilerError compilerError in compileResult.Errors)
            {
                if (compilerError.IsWarning) continue;

                string entry = "Compile error: " + compilerError.ErrorNumber + "(" + compilerError.Line + ")" + ": " + compilerError.ErrorText.Replace("{", "{{").Replace("}", "}}");

                if (verbose)
                {
                    Log.LogError(LogTitle, entry);
                }

                sb.AppendLine(entry);
            }

            throw new InvalidOperationException(sb.ToString());
        }
        /// <summary>
        /// This method will compile the type defined in <paramref name="codeGenerationBuilder"/>
        /// and return the result types. These types exists in a temp assembly, that will be
        /// deleted when the app domain is terminated.
        /// </summary>
        /// <param name="codeGenerationBuilder"></param>
        /// <param name="verbose"></param>
        /// <returns></returns>
        public static IEnumerable <Type> CompileRuntimeTempTypes(CodeGenerationBuilder codeGenerationBuilder, bool verbose = true)
        {
            int t1 = Environment.TickCount;

            _compositeGeneratedCompiled = false; // When compiling a new type, Composite.Generated.dll should always be recompiled

            var compilerParameters = new CompilerParameters
            {
                GenerateExecutable = false,
                GenerateInMemory   = false,
                OutputAssembly     = Path.Combine(TempAssemblyFolderPath, Guid.NewGuid() + ".dll")
            };

            compilerParameters.ReferencedAssemblies.AddRangeIfNotContained(codeGenerationBuilder.AssemblyLocations.ToArray());
            compilerParameters.ReferencedAssemblies.AddRangeIfNotContained(_compiledAssemblies.Select(f => f.Location).ToArray());
            compilerParameters.AddAssemblyLocationsFromBin();


            var codeCompileUnit = new CodeCompileUnit();

            codeCompileUnit.Namespaces.AddRange(codeGenerationBuilder.Namespaces.ToArray());

            var compiler      = new CSharpCodeProvider();
            var compileResult = compiler.CompileAssemblyFromDom(compilerParameters, codeCompileUnit);

            if (compileResult.Errors.Count == 0)
            {
                Assembly resultAssembly = compileResult.CompiledAssembly;

                AddCompiledAssembly(resultAssembly);

                Type[] resultTypes = resultAssembly.GetTypes();

                int t2 = Environment.TickCount;

                Log.LogVerbose(LogTitle, $"Compile '{codeGenerationBuilder.DebugLabel}' in {t2 - t1}ms");
                Log.LogVerbose(LogTitle, $"Types from : {compilerParameters.OutputAssembly}");

                foreach (Type resultType in resultTypes)
                {
                    _compiledTypesByFullName[resultType.FullName] = resultType;
                }

                return(resultTypes);
            }


#if OUTPUT_SOURCE_CODE_ON_ERROR
            using (FileStream file = File.Create(Path.Combine(PathUtil.BaseDirectory, "output.cs")))
            {
                using (var sw = new StreamWriter(file))
                {
                    compiler.GenerateCodeFromCompileUnit(codeCompileUnit, sw, new CodeGeneratorOptions());
                }
            }
#endif


            var failedAssemblyLoads = LoadAssembliesToMemory(compilerParameters.ReferencedAssemblies);

            var sb = new StringBuilder();
            failedAssemblyLoads.ForEach(asm => sb.AppendFormat("Failed to load dll: '{0}' : {1}", asm.First, asm.Second).AppendLine());

            sb.AppendLine("Failed building: " + codeGenerationBuilder.DebugLabel);
            foreach (CompilerError compilerError in compileResult.Errors)
            {
                if (compilerError.IsWarning)
                {
                    continue;
                }

                string entry = "Compile error: " + compilerError.ErrorNumber + "(" + compilerError.Line + ")" + ": " + compilerError.ErrorText.Replace("{", "{{").Replace("}", "}}");

                if (verbose)
                {
                    Log.LogError(LogTitle, entry);
                }

                sb.AppendLine(entry);
            }

            throw new InvalidOperationException(sb.ToString());
        }
        /// <summary>
        /// This method will recompile Composite.Generated.dll and drop it into bin.
        /// </summary>
        /// <param name="forceGeneration"></param>
        public static void GenerateCompositeGeneratedAssembly(bool forceGeneration = false)
        {
            if (SuppressGeneration) return;

            if (forceGeneration || !_compositeGeneratedCompiled)
            {
                lock (_lock)
                {
                    if (forceGeneration || !_compositeGeneratedCompiled)
                    {
                        Log.LogVerbose(LogTitle, string.Format("Compiling new assembly in this application domain ({0})", AppDomain.CurrentDomain.Id));

                        int t1 = Environment.TickCount;

                        var builder = new CodeGenerationBuilder("Composite.Generated.dll");
                        PopulateBuilder(builder);

                        int t2 = Environment.TickCount;

                        Compile(builder);

                        int t3 = Environment.TickCount;

                        int numberOfTypes = builder.Namespaces.SelectMany(f => f.Types.OfType<CodeTypeDeclaration>()).Count();

                        Log.LogVerbose(LogTitle, "Number of types build: " + numberOfTypes +
                                                 "\nBuilding code dom: " + (t2 - t1) + "ms" + 
                                                 "\nCompiling code dom: " + (t3 - t2) + "ms" +
                                                 "\nTotal compilation: " + (t3 - t1) + "ms");

                        _compositeGeneratedCompiled = true;

                        return;
                    }
                }
            }

            Log.LogVerbose(LogTitle, "New assembly already compiled by this application domain ({0})", AppDomain.CurrentDomain.Id);
        }
        internal static Type CreateEmptyDataClassType(DataTypeDescriptor dataTypeDescriptor, Type baseClassType = null, CodeAttributeDeclaration codeAttributeDeclaration = null)
        {
            var codeGenerationBuilder = new CodeGenerationBuilder("EmptyDataClass: " + dataTypeDescriptor.Name);
            EmptyDataClassCodeGenerator.AddAssemblyReferences(codeGenerationBuilder, dataTypeDescriptor);
            EmptyDataClassCodeGenerator.AddEmptyDataClassTypeCode(codeGenerationBuilder, dataTypeDescriptor, baseClassType, codeAttributeDeclaration);

            IEnumerable<Type> types = CodeGenerationManager.CompileRuntimeTempTypes(codeGenerationBuilder);

            return types.Single();
        }
        private InterfaceGeneratedClassesInfo InitializeStoreTypes(InterfaceConfigurationElement element,
            Dictionary<DataTypeDescriptor, IEnumerable<SqlDataTypeStoreDataScope>> allSqlDataTypeStoreDataScopes,
            Type dataContextClass,
            bool forceCompile,
            ref bool dataContextRecompilationNeeded)
        {
            HelperClassesGenerationInfo toCompile = null;

            var result = InitializeStoreTypes(element, allSqlDataTypeStoreDataScopes, dataContextClass, null, forceCompile, ref dataContextRecompilationNeeded, ref toCompile);

            if (result != null && toCompile != null)
            {
                var codeGenerationBuilder = new CodeGenerationBuilder(_dataProviderContext.ProviderName + ":" + result.InterfaceType.FullName);

                toCompile.GenerateCodeAction(codeGenerationBuilder);

                var types = CodeGenerationManager.CompileRuntimeTempTypes(codeGenerationBuilder, false).ToArray();

                toCompile.PopulateFieldsAction(types);
            }

            return result;
        }
        public void GetCodeToCompile(CodeGenerationBuilder builder)
        {
            XmlDataProvider xmlDataProvider = (XmlDataProvider)DataProviderPluginFacade.GetDataProvider(ProviderName);

            xmlDataProvider.BuildAllCode(builder);
        }
        private bool EnsureNeededTypes(DataTypeDescriptor dataTypeDescriptor, out Type dataProviderHelperType, out Type dataIdClassType, bool forceCompile = false)
        {
            lock (_lock)
            {
                // Getting the interface (ensuring that it exists)
                Type interfaceType = DataTypeTypesManager.GetDataType(dataTypeDescriptor);
                if (interfaceType == null)
                {
                    dataProviderHelperType = null;
                    dataIdClassType = null;
                    return false;
                }

                string dataProviderHelperClassFullName, dataIdClassFullName;

                GetGeneratedClassNames(dataTypeDescriptor, out dataProviderHelperClassFullName, out dataIdClassFullName);

                dataProviderHelperType = TypeManager.TryGetType(dataProviderHelperClassFullName);
                dataIdClassType = TypeManager.TryGetType(dataIdClassFullName);

                if (!forceCompile)
                {
                    forceCompile = CodeGenerationManager.IsRecompileNeeded(interfaceType, new[] { dataProviderHelperType, dataIdClassType });
                }

                if (forceCompile)
                {
                    var codeGenerationBuilder = new CodeGenerationBuilder(_dataProviderContext.ProviderName + ":" + dataTypeDescriptor.Name);

                    // XmlDataProvider types                
                    var codeBuilder = new XmlDataProviderCodeBuilder(_dataProviderContext.ProviderName, codeGenerationBuilder);
                    codeBuilder.AddDataType(dataTypeDescriptor);

                    DataWrapperCodeGenerator.AddDataWrapperClassCode(codeGenerationBuilder, dataTypeDescriptor);

                    IEnumerable<Type> types = CodeGenerationManager.CompileRuntimeTempTypes(codeGenerationBuilder, false);

                    dataProviderHelperType = types.Single(f => f.FullName == dataProviderHelperClassFullName);
                    dataIdClassType = types.Single(f => f.FullName == dataIdClassFullName);
                }

                return true;
            }
        }
        private void CompileMissingTypes(IList<GeneratedTypesInfo> typesInfo)
        {
            // Compiling missing classes
            if (typesInfo.Any(s => s.CompilationNeeded))
            {
                var codeGenerationBuilder = new CodeGenerationBuilder(_dataProviderContext.ProviderName + ":DataId and helper classes");
                var codeBuilder = new XmlDataProviderCodeBuilder(_dataProviderContext.ProviderName, codeGenerationBuilder);

                foreach (var storeToLoad in typesInfo.Where(s => s.CompilationNeeded))
                {
                    codeBuilder.AddDataType(storeToLoad.DataTypeDescriptor);

                    // Compiling some other classes for optimization
                    DataWrapperCodeGenerator.AddDataWrapperClassCode(codeGenerationBuilder, storeToLoad.DataTypeDescriptor);
                    EmptyDataClassCodeGenerator.AddEmptyDataClassTypeCode(codeGenerationBuilder, storeToLoad.DataTypeDescriptor);
                }

                var types = CodeGenerationManager.CompileRuntimeTempTypes(codeGenerationBuilder, false).ToDictionary(type => type.FullName);

                foreach (var storeToLoad in typesInfo.Where(s => s.CompilationNeeded))
                {
                    storeToLoad.DataIdClass = types[storeToLoad.DataIdClassName];
                    storeToLoad.DataProviderHelperClass = types[storeToLoad.DataProviderHelperClassName];
                }
            }
        }
        private static void Compile(CodeGenerationBuilder builder)
        {
            var compilerParameters = new CompilerParameters
            {
                GenerateExecutable = false,
                GenerateInMemory = false,
                OutputAssembly = CompositeGeneratedAssemblyPath,
                TempFiles = new TempFileCollection(TempAssemblyFolderPath)
            };

            compilerParameters.ReferencedAssemblies.AddRangeIfNotContained(builder.AssemblyLocations.ToArray());
            compilerParameters.AddAssemblyLocationsFromBin();

            var codeCompileUnit = new CodeCompileUnit();
            codeCompileUnit.Namespaces.AddRange(builder.Namespaces.ToArray());


            for (int i = 0; i < NumberOfCompileRetries; i++)
            {
                var compiler = new CSharpCodeProvider();
                CompilerResults compileResult = compiler.CompileAssemblyFromDom(compilerParameters, codeCompileUnit);


                if (compileResult.Errors.Count == 0) return;

                if (i == NumberOfCompileRetries - 1)
                {
#if OUTPUT_SOURCE_CODE_ON_ERROR
                    using (FileStream file = File.Create(Path.Combine(PathUtil.BaseDirectory, "output.cs")))
                    {
                        using (var sw = new StreamWriter(file))
                        {
                            compiler.GenerateCodeFromCompileUnit(codeCompileUnit, sw, new CodeGeneratorOptions());
                        }
                    }
#endif

                    var sb = new StringBuilder();
                    foreach (CompilerError compilerError in compileResult.Errors)
                    {
                        if (compilerError.IsWarning) continue;

                        string entry = "Compile error: " + compilerError.ErrorNumber + "(" + compilerError.Line + ")" + ": " + compilerError.ErrorText.Replace("{", "{{").Replace("}", "}}");

                        Log.LogError(LogTitle, entry);

                        sb.AppendLine(entry);
                    }

                    throw new InvalidOperationException(sb.ToString());
                }
            }
        }
        private void InitializeExistingStores()
        {
            _compositeGeneratedAssembly = _compositeGeneratedAssembly ?? AssemblyFacade.GetGeneratedAssemblyFromBin();
            _sqlDataTypeStoresContainer = new SqlDataTypeStoresContainer(_dataProviderContext.ProviderName, _connectionString, _sqlLoggingContext);

            Dictionary<DataTypeDescriptor, IEnumerable<SqlDataTypeStoreDataScope>> allSqlDataTypeStoreDataScopes = BuildAllExistingDataTypeStoreDataScopes();

            var initializedStores = new List<InterfaceGeneratedClassesInfo>();

            bool dataContextRecompilationNeeded = false;

            Type dataContextClass = TryLoadDataContext(ref dataContextRecompilationNeeded);

            var dataTypes = LoadDataTypes(_interfaceConfigurationElements);

            var compilationData = new List<HelperClassesGenerationInfo>();
            foreach (InterfaceConfigurationElement element in _interfaceConfigurationElements)
            {
                HelperClassesGenerationInfo toCompile = null;

                var generatedClassesInfo = InitializeStoreTypes(element, allSqlDataTypeStoreDataScopes,
                    dataContextClass, dataTypes, false, ref dataContextRecompilationNeeded, ref toCompile);

                if (generatedClassesInfo == null) continue;
                if (toCompile != null)
                {
                    compilationData.Add(toCompile);
                }

                initializedStores.Add(generatedClassesInfo);
            }

            if (compilationData.Any())
            {
                var codeGenerationBuilder = new CodeGenerationBuilder(_dataProviderContext.ProviderName + " : compiling missing classes");

                foreach (var toCompile in compilationData)
                {
                    toCompile.GenerateCodeAction(codeGenerationBuilder);
                }

                // Precompiling DataWrapper classes as well to improve loading time
                foreach (var interfaceType in dataTypes.Values)
                {
                    if (DataWrapperTypeManager.TryGetWrapperType(interfaceType.FullName) == null)
                    {
                        DataWrapperCodeGenerator.AddDataWrapperClassCode(codeGenerationBuilder, interfaceType);
                    }
                }

                var types = CodeGenerationManager.CompileRuntimeTempTypes(codeGenerationBuilder, false).ToArray();

                foreach (var toCompile in compilationData)
                {
                    toCompile.PopulateFieldsAction(types);
                }
            }

            if (dataContextRecompilationNeeded)
            {
                dataContextClass = DataContextAssembler.EmitDataContextClass(
                    initializedStores
                    .Where(s => s.Fields != null)
                    .SelectMany(s => s.Fields.Values).Evaluate());
            }

            _sqlDataTypeStoresContainer.DataContextClass = dataContextClass;

            foreach (var typeInfo in initializedStores)
            {
                var store = EmbedDataContextInfo(typeInfo, dataContextClass);

                AddDataTypeStore(store, true, true);
            }
        }
 private static void PopulateBuilder(CodeGenerationBuilder builder)
 {
     foreach (ICodeProvider provider in CodeProviders)
     {
         provider.GetCodeToCompile(builder);
     }
 }
        public void CreateStores(IReadOnlyCollection<DataTypeDescriptor> dataTypeDescriptors)
        {
            var types = DataTypeTypesManager.GetDataTypes(dataTypeDescriptors);

            foreach (var dataTypeDescriptor in dataTypeDescriptors)
            {
                if (InterfaceConfigurationManipulator.ConfigurationExists(_dataProviderContext.ProviderName, dataTypeDescriptor))
                {
                    throw new InvalidOperationException(string.Format("SqlDataProvider configuration already contains a interface named '{0}'. Remove it from the configuration and restart the application.", dataTypeDescriptor.TypeManagerTypeName));
                }
            }

            // Creating Sql tables and adding to the configuration
            var configElements = new Dictionary<DataTypeDescriptor, InterfaceConfigurationElement>();

            foreach (var dataTypeDescriptor in dataTypeDescriptors)
            {
                Type type = types[dataTypeDescriptor.DataTypeId];

                Action<string> existingTablesValidator = tableName =>
                {
                    var errors = new StringBuilder();
                    var interfaceType = type;
                    if (!ValidateTable(interfaceType, tableName, errors))
                    {
                        throw new InvalidOperationException("Table '{0}' already exist but isn't valid: {1}".FormatWith(tableName, errors.ToString()));
                    }
                };

                SqlStoreManipulator.CreateStoresForType(dataTypeDescriptor, existingTablesValidator);

                InterfaceConfigurationElement element = InterfaceConfigurationManipulator.AddNew(_dataProviderContext.ProviderName, dataTypeDescriptor);
                _interfaceConfigurationElements.Add(element);

                configElements.Add(dataTypeDescriptor, element);
            }

            // Generating necessary classes and performing validation
            Dictionary<DataTypeDescriptor, IEnumerable<SqlDataTypeStoreDataScope>> allSqlDataTypeStoreDataScopes = BuildAllExistingDataTypeStoreDataScopes();

            bool dataContextRecompilationNeeded = false;

            var toCompileList = new List<HelperClassesGenerationInfo>();
            var generatedClassesInfo = new Dictionary<DataTypeDescriptor, InterfaceGeneratedClassesInfo>();

            Type dataContextClass = _sqlDataTypeStoresContainer.DataContextClass;

            foreach (var dataTypeDescriptor in dataTypeDescriptors)
            {
                var element = configElements[dataTypeDescriptor];

                // InitializeStoreResult initializeStoreResult = InitializeStore(element, allSqlDataTypeStoreDataScopes);

                HelperClassesGenerationInfo toCompile = null;

                var classesInfo = InitializeStoreTypes(element, allSqlDataTypeStoreDataScopes, dataContextClass, null, false, ref dataContextRecompilationNeeded, ref toCompile);

                if (classesInfo != null && toCompile != null)
                {
                    toCompileList.Add(toCompile);

                    generatedClassesInfo[dataTypeDescriptor] = classesInfo;
                }
            }

            // Compiling missing classes
            if (toCompileList.Any())
            {
                var codeGenerationBuilder = new CodeGenerationBuilder(_dataProviderContext.ProviderName + ":CreateStores");

                foreach (var toCompile in toCompileList)
                {
                    toCompile.GenerateCodeAction(codeGenerationBuilder);
                }

                var generatedHelperClasses = CodeGenerationManager.CompileRuntimeTempTypes(codeGenerationBuilder, false).ToArray();

                foreach (var toCompile in toCompileList)
                {
                    toCompile.PopulateFieldsAction(generatedHelperClasses);
                }
            }

            // Emitting a new DataContext class
            if (dataContextRecompilationNeeded)
            {
                var newDataTypeIds = new HashSet<Guid>(dataTypeDescriptors.Select(d => d.DataTypeId));

                _createdSqlDataTypeStoreTables.RemoveAll(f => newDataTypeIds.Contains(f.DataTypeId));

                var fields = _createdSqlDataTypeStoreTables.Select(s => new Tuple<string, Type>(s.DataContextFieldName, s.DataContextFieldType)).ToList();

                foreach (var classesInfo in generatedClassesInfo.Values)
                {
                    fields.AddRange(classesInfo.Fields.Select(f => new Tuple<string, Type>(f.Value.FieldName, f.Value.FieldType)));
                }

                dataContextClass = DataContextAssembler.EmitDataContextClass(fields);

                UpdateCreatedSqlDataTypeStoreTables(dataContextClass);
            }

            _sqlDataTypeStoresContainer.DataContextClass = dataContextClass;

            // Registering the new type/tables
            foreach (var dataTypeDescriptor in dataTypeDescriptors)
            {
                InterfaceGeneratedClassesInfo classesInfo;

                if (!generatedClassesInfo.TryGetValue(dataTypeDescriptor, out classesInfo))
                {
                    throw new InvalidOperationException("No generated classes for data type '{0}' found".FormatWith(dataTypeDescriptor.Name));
                }
                InitializeStoreResult initInfo = EmbedDataContextInfo(classesInfo, dataContextClass);

                AddDataTypeStore(initInfo, false);
            }
        }
        internal static Dictionary<Guid, Type> GetDataTypes(IReadOnlyCollection<DataTypeDescriptor> dataTypeDescriptors)
        {
            var result = new Dictionary<Guid, Type>();
            var toCompile = new List<DataTypeDescriptor>();

            foreach (var dataTypeDescriptor in dataTypeDescriptors)
            {
                string typeFullName = dataTypeDescriptor.GetFullInterfaceName();
                Type type = _LoadedDataTypes.FirstOrDefault(f => f.FullName == typeFullName);
                if (type == null)
                {
                    bool compilationNeeded;
                    type = InterfaceCodeManager.TryGetType(dataTypeDescriptor, false, out compilationNeeded);

                    if (compilationNeeded)
                    {
                        toCompile.Add(dataTypeDescriptor);
                    }
                }

                if (type != null)
                {
                    result[dataTypeDescriptor.DataTypeId] = type;
                }
            }

            if (toCompile.Any())
            {
                var codeGenerationBuilder = new CodeGenerationBuilder("DataTypeTypesManager:compiling missing interfaces");

                foreach (var dataTypeDescriptor in toCompile)
                {
                    InterfaceCodeGenerator.AddAssemblyReferences(codeGenerationBuilder, dataTypeDescriptor);
                    InterfaceCodeGenerator.AddInterfaceTypeCode(codeGenerationBuilder, dataTypeDescriptor);
                }

                var types = CodeGenerationManager.CompileRuntimeTempTypes(codeGenerationBuilder);
                var typesMap = types.ToDictionary(type => type.FullName);

                foreach (var dataTypeDescriptor in toCompile)
                {
                    var type = typesMap[dataTypeDescriptor.GetFullInterfaceName()];
                    result[dataTypeDescriptor.DataTypeId] = type;
                }
            }

            return result;
        }