public static IEnumerable<IDocumentStorage> Build(IDocumentSchema schema, DocumentMapping[] mappings) { // Generate the actual source code var code = GenerateDocumentStorageCode(mappings); var generator = new AssemblyGenerator(); // Tell the generator which other assemblies that it should be referencing // for the compilation generator.ReferenceAssembly(Assembly.GetExecutingAssembly()); generator.ReferenceAssemblyContainingType<NpgsqlConnection>(); generator.ReferenceAssemblyContainingType<QueryModel>(); generator.ReferenceAssemblyContainingType<DbCommand>(); generator.ReferenceAssemblyContainingType<Component>(); generator.ReferenceAssemblyContainingType<DbDataReader>(); mappings.Select(x => x.DocumentType.Assembly).Distinct().Each(assem => generator.ReferenceAssembly(assem)); // build the new assembly -- this will blow up if there are any // compilation errors with the list of errors and the actual code var assembly = generator.Generate(code); return assembly .GetExportedTypes() .Where(x => x.IsConcreteTypeOf<IDocumentStorage>()) .Select(x => BuildStorageObject(schema, mappings, x)); }
public static IEnumerable <IDocumentStorage> Build(IDocumentSchema schema, DocumentMapping[] mappings) { // Generate the actual source code var code = GenerateDocumentStorageCode(mappings); var generator = new AssemblyGenerator(); // Tell the generator which other assemblies that it should be referencing // for the compilation generator.ReferenceAssembly(Assembly.GetExecutingAssembly()); generator.ReferenceAssemblyContainingType <NpgsqlConnection>(); generator.ReferenceAssemblyContainingType <QueryModel>(); generator.ReferenceAssemblyContainingType <DbCommand>(); generator.ReferenceAssemblyContainingType <Component>(); generator.ReferenceAssemblyContainingType <DbDataReader>(); mappings.Select(x => x.DocumentType.Assembly).Distinct().Each(assem => generator.ReferenceAssembly(assem)); // build the new assembly -- this will blow up if there are any // compilation errors with the list of errors and the actual code var assembly = generator.Generate(code); return(assembly .GetExportedTypes() .Where(x => x.IsConcreteTypeOf <IDocumentStorage>()) .Select(x => BuildStorageObject(schema, mappings, x))); }
public static IEnumerable<IDocumentStorage> Build(IDocumentSchema schema, DocumentMapping[] mappings) { var code = GenerateDocumentStorageCode(mappings); var generator = new AssemblyGenerator(); generator.ReferenceAssembly(Assembly.GetExecutingAssembly()); generator.ReferenceAssemblyContainingType<NpgsqlConnection>(); generator.ReferenceAssemblyContainingType<QueryModel>(); generator.ReferenceAssemblyContainingType<DbCommand>(); generator.ReferenceAssemblyContainingType<Component>(); mappings.Select(x => x.DocumentType.Assembly).Distinct().Each(assem => generator.ReferenceAssembly(assem)); var assembly = generator.Generate(code); return assembly .GetExportedTypes() .Where(x => x.IsConcreteTypeOf<IDocumentStorage>()) .Select(x => { var docType = x.FindInterfaceThatCloses(typeof (IdAssignment<>)).GetGenericArguments().Single(); var mapping = mappings.Single(m => m.DocumentType == docType); var arguments = mapping.IdStrategy.ToArguments().Select(arg => arg.GetValue(schema)).ToArray(); var ctor = x.GetConstructors().Single(); return ctor.Invoke(arguments).As<IDocumentStorage>(); }); }
// Public methods /////////////////////////// public static Action Create(Ecs.Internals ecs, MethodInfo systemInfo) { var systemName = $"{systemInfo.DeclaringType}.{systemInfo.Name}"; var arguments = systemInfo.GetParameters() .Select(p => GetArgumentData(ecs, p)) .ToArray(); if (arguments.Length == 0) { return(() => systemInfo.Invoke(null, null)); } var resources = arguments .Where(a => a.isResource) .ToArray(); var components = arguments .Where(a => !a.isResource) .ToArray(); var src = default(string); if (components.Length > 0) { src = ForEachSource(ecs, arguments, resources, components); } else { src = ResourceOnlySource(ecs, resources); } var asmGen = new AssemblyGenerator(); asmGen.ReferenceAssemblyByName("System"); asmGen.ReferenceAssemblyByName("System.Collections"); asmGen.ReferenceAssemblyByName("System.Reflection"); asmGen.ReferenceAssemblyContainingType(typeof(Ecs)); src = asmGen.Format(src); var startTime = TimeNow(); var(assembly, errors) = asmGen.Generate(src); if (errors != null) { var sb = new System.Text.StringBuilder(); sb.Append($"encountered error(s) compiling system runner for {systemName}"); foreach (var error in errors) { sb.Append($"\n {error.Replace("\n", "\n ")}"); } var srcLines = src.Split("\n"); for (var i = 0; i < srcLines.Length; i++) { sb.Append($"\n{i+1}\t{srcLines[i]}"); } throw new Exception(sb.ToString()); } var runner = assembly.GetType("Runner"); var duration = TimeNow() - startTime; Console.WriteLine($"generated system runner for {systemName} in {duration}ms:\n {src.Replace("\n", "\n ")}"); runner.GetMethod("Initialize").Invoke(null, new object[] { ecs, systemInfo }); return((Action)runner.GetMethod("Run").CreateDelegate(typeof(Action))); }
public static IEnumerable<IDocumentStorage> Build(DocumentMapping[] mappings) { var code = GenerateDocumentStorageCode(mappings); var generator = new AssemblyGenerator(); generator.ReferenceAssembly(Assembly.GetExecutingAssembly()); generator.ReferenceAssemblyContainingType<NpgsqlConnection>(); generator.ReferenceAssemblyContainingType<QueryModel>(); generator.ReferenceAssemblyContainingType<DbCommand>(); generator.ReferenceAssemblyContainingType<Component>(); mappings.Select(x => x.DocumentType.Assembly).Distinct().Each(assem => generator.ReferenceAssembly(assem)); var assembly = generator.Generate(code); return assembly .GetExportedTypes() .Where(x => x.IsConcreteTypeOf<IDocumentStorage>()) .Select(x => Activator.CreateInstance(x).As<IDocumentStorage>()); }
public static IEnumerable <IDocumentStorage> Build(IDocumentSchema schema, IDocumentMapping[] mappings) { // Generate the actual source code var code = GenerateDocumentStorageCode(mappings); var generator = new AssemblyGenerator(); // Tell the generator which other assemblies that it should be referencing // for the compilation generator.ReferenceAssembly(Assembly.GetExecutingAssembly()); generator.ReferenceAssemblyContainingType <NpgsqlConnection>(); generator.ReferenceAssemblyContainingType <QueryModel>(); generator.ReferenceAssemblyContainingType <DbCommand>(); generator.ReferenceAssemblyContainingType <Component>(); generator.ReferenceAssemblyContainingType <DbDataReader>(); mappings.Select(x => x.DocumentType.Assembly).Distinct().Each(assem => generator.ReferenceAssembly(assem)); // build the new assembly -- this will blow up if there are any // compilation errors with the list of errors and the actual code var assembly = generator.Generate(code); return(assembly .GetExportedTypes() .Where(x => x.IsConcreteTypeOf <IDocumentStorage>()) .Select(x => { var docType = x.FindInterfaceThatCloses(typeof(IdAssignment <>)).GetGenericArguments().Single(); var mapping = mappings.Single(m => m.DocumentType == docType); var arguments = mapping.ToArguments().Select(arg => arg.GetValue(schema)).ToArray(); var ctor = x.GetConstructors().Single(); return ctor.Invoke(arguments).As <IDocumentStorage>(); })); }
public static IEnumerable<IDocumentStorage> Build(IDocumentSchema schema, IDocumentMapping[] mappings) { // Generate the actual source code var code = GenerateDocumentStorageCode(mappings); var generator = new AssemblyGenerator(); // Tell the generator which other assemblies that it should be referencing // for the compilation generator.ReferenceAssembly(Assembly.GetExecutingAssembly()); generator.ReferenceAssemblyContainingType<NpgsqlConnection>(); generator.ReferenceAssemblyContainingType<QueryModel>(); generator.ReferenceAssemblyContainingType<DbCommand>(); generator.ReferenceAssemblyContainingType<Component>(); generator.ReferenceAssemblyContainingType<DbDataReader>(); mappings.Select(x => x.DocumentType.Assembly).Distinct().Each(assem => generator.ReferenceAssembly(assem)); // build the new assembly -- this will blow up if there are any // compilation errors with the list of errors and the actual code var assembly = generator.Generate(code); return assembly .GetExportedTypes() .Where(x => x.IsConcreteTypeOf<IDocumentStorage>()) .Select(x => { var docType = x.FindInterfaceThatCloses(typeof (IdAssignment<>)).GetGenericArguments().Single(); var mapping = mappings.Single(m => m.DocumentType == docType); var arguments = mapping.ToArguments().Select(arg => arg.GetValue(schema)).ToArray(); var ctor = x.GetConstructors().Single(); return ctor.Invoke(arguments).As<IDocumentStorage>(); }); }
public static IEnumerable <IDocumentStorage> Build(DocumentMapping[] mappings) { var code = GenerateDocumentStorageCode(mappings); var generator = new AssemblyGenerator(); generator.ReferenceAssembly(Assembly.GetExecutingAssembly()); generator.ReferenceAssemblyContainingType <NpgsqlConnection>(); generator.ReferenceAssemblyContainingType <QueryModel>(); generator.ReferenceAssemblyContainingType <DbCommand>(); generator.ReferenceAssemblyContainingType <Component>(); mappings.Select(x => x.DocumentType.Assembly).Distinct().Each(assem => generator.ReferenceAssembly(assem)); var assembly = generator.Generate(code); return(assembly .GetExportedTypes() .Where(x => x.IsConcreteTypeOf <IDocumentStorage>()) .Select(x => Activator.CreateInstance(x).As <IDocumentStorage>())); }
static (Action, bool) Compile(string fileName) { var startTime = Time.Now(); var source = File.ReadAllText(fileName); var asmGen = new AssemblyGenerator(); asmGen.ReferenceAssemblyByName("System.Collections"); asmGen.ReferenceAssemblyByName("System.Linq"); asmGen.ReferenceAssemblyContainingType(typeof(Program)); source = asmGen.Format(source); var(assembly, errors) = asmGen.Generate(source); if (errors != null) { Log.Error($"compilation error:\n{String.Join("\n", errors)}"); return(null, false); } var scriptType = assembly.GetType("Script"); var mainMethod = scriptType.GetMethod("Main", BindingFlags.NonPublic | BindingFlags.Static); var run = (Action)mainMethod.CreateDelegate(typeof(Action)); var duration = Time.Now() - startTime; Log.Info($"compiled script {fileName} in {duration:F2}s"); return(run, true); }
public ObjectBinder(IDictionary <Expression <Func <TSource, object> >, Expression <Func <TCommon, object> > > map, AssemblyGenerator assemblyGenerator) { var sourceType = typeof(TSource); var commonType = typeof(TCommon); Guard.Argument(commonType) .Require(x => x.IsInterface || x.GetConstructor(Type.EmptyTypes) != null, x => "Common type must be either an interface or provide parameterless constructor" ); assemblyGenerator.ReferenceAssemblyContainingType <TSource>(); assemblyGenerator.ReferenceAssemblyContainingType <TCommon>(); var visitedCommonProperties = ImmutableList <PropertyInfo> .Empty; var(shadowField, constructorArg) = ("_sourceRef", "sourceRef"); var assembly = assemblyGenerator.Generate(opt => { var className = $"{commonType.Name}_proxy_{_count++}"; opt.UsingNamespace <TSource>(); opt.UsingNamespace <TCommon>(); opt.Namespace($"LamarGenerated.Proxy.{sourceType.Name}_{commonType.Name}"); opt.StartClass(className, typeof(TCommon)); // Shadow field opt.Write($"private readonly {sourceType.FullNameInCode()} {shadowField};"); opt.BlankLine(); // Constructor opt.Write($"BLOCK:public {className} ({sourceType.FullNameInCode()} {constructorArg})"); opt.Write($"{shadowField} = {constructorArg};"); opt.FinishBlock(); foreach (var(key, value) in map) { var(prop1, prop2) = (ResolveMemberExpression(key), ResolveMemberExpression(value)); visitedCommonProperties = visitedCommonProperties.Add(prop2); Guard.Argument((prop1, prop2)) .Require(x => x.Item1 != null) .Require(x => x.Item2 != null) .Require(x => x.Item1.PropertyType == x.Item2.PropertyType, tuple => $"Property types between {tuple.Item1.PropertyType} and {tuple.Item2.PropertyType} do not match"); // If TCommon is not an interface and if property of common is virtual, then we can override it else // it causes property duplication as overriding property is not possible var needsOverride = false; if (!commonType.IsInterface) { needsOverride = prop2.GetGetMethod().IsVirtual ? true : throw new Exception($"TCommon type is not an interface and property {prop2.Name} of" + "Common type is not virtual hence it causes property duplication"); } opt.Write( $"public {(needsOverride ? "override" : string.Empty)} {prop1.PropertyType.FullNameInCode()} {prop2.Name} " + "{" + $@" get {{ return {shadowField}.{prop1.Name}; }} " + $@" set {{ {shadowField}.{prop1.Name} = value; }} " + "}"); opt.BlankLine(); } // If common type is not an interface, hence we need to add the properties, otherwise, they will be inherited if (commonType.IsInterface) { // Add the rest of properties that do not needed be bound foreach (var propertyInfo in commonType.GetProperties().Except(visitedCommonProperties)) { opt.Write( $"public {propertyInfo.PropertyType.FullNameInCode()} {propertyInfo.Name} {{ get; set; }} "); opt.BlankLine(); } } opt.FinishBlock(); // Finish the class opt.FinishBlock(); // Finish the namespace }); BoundType = assembly.GetExportedTypes().Single(); }