public IGenerateResult Build() { var compileBuilder = new CompilationBuilder(_diagnostics); var assemblyBuilder = new AssemblyBuilder(_diagnostics); var compile = compileBuilder.Create(); var results = _hash.SelectMany(x => x.Value.GenerateTypes(compile)); var syntaxes = results.Select(x => x.Syntax).ToArray(); var assembly = assemblyBuilder.CraeteAssembly(compile, syntaxes); if (assembly != null) { var generateResults = from result in results let type = assembly.GetType($"{assemblyBuilder.AssemblyNamespace}.{result.TypeName}") select new TypeBuilderResult(result.GenerateType, result.OriginType, type); return(new GenerateResult(true, generateResults.ToArray())); } return(new GenerateResult(false, default)); }
public void GenerateServiceFactoryForScopedClass() { // Given var input = CompilationBuilder.CreateAssemblyWithCode( @"namespace Demo.Domain { public interface IFoo { } }", @"namespace Demo.Domain { using CustomCode.CompileTimeInject.Annotations; [Export(Lifetime.Scoped)] public sealed class Foo : IFoo { } }"); var sourceGenerator = new ServiceFactoryGenerator(); var testEnvironment = CSharpGeneratorDriver.Create(sourceGenerator); // When testEnvironment.RunGeneratorsAndUpdateCompilation( compilation: input, outputCompilation: out var output, diagnostics: out var diagnostics); // Then Assert.False(diagnostics.HasErrors()); Assert.True(output.ContainsTypeWithMethodImplementation( "ServiceFactory", @"Demo.Domain.IFoo IServiceFactory<Demo.Domain.IFoo>.CreateOrGetService() { var service = (Demo.Domain.IFoo)ScopedInstances.GetOrAdd(typeof(Demo.Domain.IFoo), _ => { var service = new Demo.Domain.Foo(); return service; }); return service; }")); }
public void GenerateGetServicesForNamedServicesWithScopes() { // Given var input = CompilationBuilder.CreateAssemblyWithCode( @"namespace Demo.Domain { public interface IFoo { } }", @"namespace Demo.Domain { using CustomCode.CompileTimeInject.Annotations; [Export(Lifetime.Scoped, ServiceId = ""1"")] public sealed class Foo : IFoo { } }"); var sourceGenerator = new IocContainerGenerator(); var runtime = CSharpGeneratorDriver.Create(sourceGenerator); // When runtime.RunGeneratorsAndUpdateCompilation( compilation: input, outputCompilation: out var output, diagnostics: out var diagnostics); // Then Assert.False(diagnostics.HasErrors()); Assert.True(output.ContainsTypeWithMethodImplementation( "IocContainer", @"public T? GetService<T>(string serviceId) where T : class { var scope = GetActiveScope(); var service = scope.GetService<T>(serviceId); return service; }")); }
public void GenerateServiceCacheForNamedServices() { // Given var input = CompilationBuilder.CreateAssemblyWithCode( @"namespace Demo.Domain { public interface IFoo { } }", @"namespace Demo.Domain { using CustomCode.CompileTimeInject.Annotations; [Export(ServiceId = ""1"")] public sealed class Foo : IFoo { } }"); var sourceGenerator = new ServiceCacheGenerator(); var testEnvironment = CSharpGeneratorDriver.Create(sourceGenerator); // When testEnvironment.RunGeneratorsAndUpdateCompilation( compilation: input, outputCompilation: out var output, diagnostics: out var diagnostics); // Then Assert.False(diagnostics.HasErrors()); Assert.True(output.ContainsClass("ServiceCache")); Assert.True(output.ContainsTypeWithMethodImplementation( "ServiceCache", @"public object GetOrAdd(Type key, string serviceId, Func<string, object> valueFactory) { var cache = NamedServiceCache.GetOrAdd(key, new ConcurrentDictionary<string, object>()); return cache.GetOrAdd(serviceId, valueFactory); }")); }
/// <summary> /// Create in-memory compilation of library /// </summary> private void CreateLibrary() { if (string.IsNullOrEmpty(_settings.LibraryRootDirectory) || !Directory.Exists(_settings.LibraryRootDirectory)) { return; } try { lock ( Sync ) { var builder = new CompilationBuilder(); // adding all *.cs files foreach (var path in Directory.GetFiles(_settings.LibraryRootDirectory, "*.cs", SearchOption.AllDirectories)) { builder.AddSourceFile(path); } _compilation = builder.Build(); var errors = builder.ValidateCompilation(_compilation); if (errors != null && errors.Any()) { MessageBox.Show("There were compilation errors of library: " + Environment.NewLine + string.Join(Environment.NewLine, errors)); } _codeImporter = new CodeImporter(_compilation, location => File.ReadAllText(location.FileName).Substring(location.Span.Start, location.Span.Length)); } } catch (Exception ex) { MessageBox.Show("Error during library compilation: " + ex.Message); } }
public void GenerateScopeGetServiceMethod() { // Given var input = CompilationBuilder.CreateAssemblyWithCode( @"namespace Demo.Domain { public interface IFoo { } }", @"namespace Demo.Domain { using CustomCode.CompileTimeInject.Annotations; [Export(Lifetime.Scoped)] public sealed class Foo : IFoo { } }"); var sourceGenerator = new ScopeGenerator(); var testEnvironment = CSharpGeneratorDriver.Create(sourceGenerator); // When testEnvironment.RunGeneratorsAndUpdateCompilation( compilation: input, outputCompilation: out var output, diagnostics: out var diagnostics); // Then Assert.False(diagnostics.HasErrors()); Assert.True(output.ContainsTypeWithMethodImplementation( "Scope", @"public T? GetService<T>() where T : class { var factory = Factory as IServiceFactory<T>; return factory?.CreateOrGetService(); }")); }
public void GenerateServiceFactoryForClassWithSingleGenericInterfaceWithValueTypeParameter() { // Given var input = CompilationBuilder.CreateAssemblyWithCode( @"namespace Demo.Domain { public interface IFoo<T> { } }", @"namespace Demo.Domain { using CustomCode.CompileTimeInject.Annotations; [Export] public sealed class Foo : IFoo<int> { } }"); var sourceGenerator = new ServiceFactoryGenerator(); var testEnvironment = CSharpGeneratorDriver.Create(sourceGenerator); // When testEnvironment.RunGeneratorsAndUpdateCompilation( compilation: input, outputCompilation: out var output, diagnostics: out var diagnostics); // Then Assert.False(diagnostics.HasErrors()); Assert.True(output.ContainsTypeWithMethodImplementation( "ServiceFactory", @"Demo.Domain.IFoo<int> IServiceFactory<Demo.Domain.IFoo<int>>.CreateOrGetService() { var service = new Demo.Domain.Foo(); return service; }")); }
public void GenerateServiceFactoryForTransientClassWithTwoDependencies() { // Given var input = CompilationBuilder.CreateAssemblyWithCode( @"namespace Demo.Domain { public interface IFirstBar { } }", @"namespace Demo.Domain { using CustomCode.CompileTimeInject.Annotations; [Export] public sealed class FirstBar : IFirstBar { } }", @"namespace Demo.Domain { public interface ISecondBar { } }", @"namespace Demo.Domain { using CustomCode.CompileTimeInject.Annotations; [Export] public sealed class SecondBar : ISecondBar { } }", @"namespace Demo.Domain { public interface IFoo { } }", @"namespace Demo.Domain { using CustomCode.CompileTimeInject.Annotations; [Export(Lifetime.Transient)] public sealed class Foo : IFoo { public Foo(IFirstBar firstBar, ISecondBar secondBar) { FirstBar = firstBar; SecondBar = secondBar; } private IFirstBar FirstBar { get; } private ISecondBar SecondBar { get; } } }"); var sourceGenerator = new ServiceFactoryGenerator(); var testEnvironment = CSharpGeneratorDriver.Create(sourceGenerator); // When testEnvironment.RunGeneratorsAndUpdateCompilation( compilation: input, outputCompilation: out var output, diagnostics: out var diagnostics); // Then Assert.False(diagnostics.HasErrors()); Assert.True(output.ContainsTypeWithMethodImplementation( "ServiceFactory", @"Demo.Domain.IFoo IServiceFactory<Demo.Domain.IFoo>.CreateOrGetService() { var dependency1 = ((IServiceFactory<Demo.Domain.IFirstBar>)this).CreateOrGetService(); var dependency2 = ((IServiceFactory<Demo.Domain.ISecondBar>)this).CreateOrGetService(); var service = new Demo.Domain.Foo(dependency1, dependency2); return service; }")); }
public void GenerateServiceFactoryForSingletonClassWithSingleDependencyFactory() { // Given var input = CompilationBuilder.CreateAssemblyWithCode( @"namespace Demo.Domain { public interface IBar { } }", @"namespace Demo.Domain { using CustomCode.CompileTimeInject.Annotations; [Export] public sealed class Bar : IBar { } }", @"namespace Demo.Domain { public interface IFoo { } }", @"namespace Demo.Domain { using CustomCode.CompileTimeInject.Annotations; using System; [Export(Lifetime.Singleton)] public sealed class Foo : IFoo { public Foo(Func<IBar> barFactory) { BarFactory = barFactory; } private Func<IBar> BarFactory { get; } } }"); var sourceGenerator = new ServiceFactoryGenerator(); var testEnvironment = CSharpGeneratorDriver.Create(sourceGenerator); // When testEnvironment.RunGeneratorsAndUpdateCompilation( compilation: input, outputCompilation: out var output, diagnostics: out var diagnostics); // Then Assert.False(diagnostics.HasErrors()); Assert.True(output.ContainsTypeWithMethodImplementation( "ServiceFactory", @"Demo.Domain.IFoo IServiceFactory<Demo.Domain.IFoo>.CreateOrGetService() { var service = (Demo.Domain.IFoo)SingletonInstances.GetOrAdd(typeof(Demo.Domain.IFoo), _ => { var dependency1 = new Func<Demo.Domain.IBar>(((IServiceFactory<Demo.Domain.IBar>)this).CreateOrGetService); var service = new Demo.Domain.Foo(dependency1); return service; }); return service; }")); }
public void 编译程序集() { // 编译选项 DomainOptionBuilder option = new DomainOptionBuilder() .WithPlatform(Platform.AnyCpu) // 生成可移植程序集 .WithDebug(false) // 使用 Release 编译 .WithKind(OutputKind.DynamicallyLinkedLibrary) // 生成动态库 .WithLanguageVersion(LanguageVersion.CSharp7_3); // 使用 C# 7.3 CompilationBuilder builder = CodeSyntax.CreateCompilation("Test.dll") .WithPath(Directory.GetParent(typeof(CompilationTests).Assembly.Location).FullName) .WithOption(option) .WithAutoAssembly() // 自动添加程序集引用 .WithNamespace(NamespaceBuilder.FromCode(@"using System; namespace MySpace { public class Test { public string MyMethod() { Console.WriteLine(""程序集运行成功""); return ""测试成功""; } } } ")); try { if (builder.CreateDomain(out var messages)) { Console.WriteLine("编译成功!开始执行程序集进行验证!"); var assembly = Assembly.LoadFile(Directory.GetParent(typeof(CompilationTests).Assembly.Location).FullName + "/Test.dll"); var type = assembly.GetType("MySpace.Test"); var method = type.GetMethod("MyMethod"); object obj = Activator.CreateInstance(type); string result = (string)method.Invoke(obj, null); if (result.Equals("测试成功")) { Console.WriteLine("执行程序集测试成功!"); } else { Console.WriteLine("执行程序集测试失败!"); } } else { _ = messages.Execute(item => { Console.WriteLine(@$ "ID:{item.Id} 严重程度:{item.Severity} 位置:{item.Location.SourceSpan.Start}~{item.Location.SourceSpan.End} 消息:{item.Descriptor.Title} {item}"); }); } } catch (Exception ex) { Console.WriteLine($"{ex.ToString()}"); } }
static void Main(string[] args) { PropertyInfo info = typeof(Program).GetProperty("a"); Console.WriteLine(info.Attributes.ToString()); // 编译选项 // 编译选项可以不配置 DomainOptionBuilder option = new DomainOptionBuilder() .WithPlatform(Platform.AnyCpu) // 生成可移植程序集 .WithDebug(false) // 使用 Release 编译 .WithKind(OutputKind.DynamicallyLinkedLibrary) // 生成动态库 .WithLanguageVersion(LanguageVersion.CSharp7_3); // 使用 C# 7.3 CompilationBuilder builder = CodeSyntax.CreateCompilation("Test.dll") .WithPath(Directory.GetParent(typeof(Program).Assembly.Location).FullName) .WithOption(option) // 可以省略 .WithAutoAssembly() // 自动添加程序集引用 .WithNamespace(NamespaceBuilder.FromCode(@"using System; namespace MySpace { public class Test { public string MyMethod() { Console.WriteLine(""程序集运行成功""); return ""测试成功""; } } } ")); try { if (builder.CreateDomain(out var messages)) { Console.WriteLine("编译成功!开始执行程序集进行验证!"); var assembly = Assembly.LoadFile(Directory.GetParent(typeof(Program).Assembly.Location).FullName + "/Test.dll"); var type = assembly.GetType("MySpace.Test"); var method = type.GetMethod("MyMethod"); object obj = Activator.CreateInstance(type); string result = (string)method.Invoke(obj, null); if (result.Equals("测试成功")) { Console.WriteLine("执行程序集测试成功!"); } else { Console.WriteLine("执行程序集测试失败!"); } } else { _ = messages.Execute(item => { Console.WriteLine(@$ "ID:{item.Id} 严重程度:{item.Severity} 位置:{item.Location.SourceSpan.Start}~{item.Location.SourceSpan.End} 消息:{item.Descriptor.Title} {item}"); }); } } catch (Exception ex) { Console.WriteLine($"{ex.ToString()}"); } //List<PortableExecutableReference> references = assemblies.Select(c => MetadataReference.CreateFromStream(c)).ToList(); //var tmp = DependencyContext.Default.RuntimeLibraries // .Execute(item => // { // item.Dependencies.Execute(itemNode => // { // var t = $"{itemNode.Name}.dll"; // Console.WriteLine(item.Path + "|" + item.HashPath + "|" + item.Path); // var c = MetadataReference.CreateFromFile(t); // references.Add(c); // }); // }).ToArray(); //PortableExecutableReference[] mscorlibs = references.ToArray(); //PortableExecutableReference mscorlib = MetadataReference.CreateFromFile(typeof(object).Assembly.Location); //CSharpCompilation compilation = CSharpCompilation.Create("MyCompilation", // syntaxTrees: new[] { tree }, references: mscorlibs); ////Emitting to file is available through an extension method in the Microsoft.CodeAnalysis namespace //EmitResult emitResult = compilation.Emit("output.dll", "output.pdb"); ////If our compilation failed, we can discover exactly why. //if (!emitResult.Success) //{ // foreach (var diagnostic in emitResult.Diagnostics) // { // Console.WriteLine(diagnostic.ToString()); // } //} //var a = DependencyContext.Default.CompileLibraries; //var b = a.Count; //foreach (var item in DependencyContext.Default.CompileLibraries.SelectMany(cl=>cl.ResolveReferencePaths())) //{ // Console.WriteLine(item); //} //GenericBuilder generic = new GenericBuilder(); //generic.AddConstarint(new GenericScheme("T1", GenericConstraintsType.Struct)); //generic.AddConstarint(new GenericScheme("T2", GenericConstraintsType.Class)); //generic.AddConstarint(new GenericScheme("T3", GenericConstraintsType.Notnull)); //generic.AddConstarint(new GenericScheme("T4", GenericConstraintsType.Unmanaged)); //generic.AddConstarint(new GenericScheme("T5", GenericConstraintsType.New)); //// 如果能够反射拿到 Type //generic.AddConstarint(new GenericScheme("T6", GenericConstraintsType.BaseClass, typeof(int))); //// 如果要以字符串定义基类类型,请使用 此API //generic.AddBaseClassConstarint("T7", " IEnumerable<int>"); //generic.AddTUConstarint("T8", "T2"); //generic.AddConstarint(new GenericScheme("T9", GenericConstraintsType.Class, GenericConstraintsType.New)); //var syntax = generic.Build(); //var result = syntax.ToFullString(); //Console.WriteLine(result); //ClassBuilder buidler = new ClassBuilder(); //var build = buidler.SetVisibility(ClassVisibilityType.Public) // .SetName("Test") // .AddMethodMember(b => // { // b.SetVisibility(MemberVisibilityType.Public) // .SetRondomName() // .SetBlock("System.Console.WriteLine(\"111\");"); // }) // .Build(); // CompilationBuilder compilation = new CompilationBuilder(); //compilation.Test(build); Console.ReadKey(); }
public void GenerateTwoScopedNamedServices() { // Given var input = CompilationBuilder.CreateAssemblyWithCode( @"namespace Demo.Domain { public interface IFoo { string Id { get; } } }", @"namespace Demo.Domain { using CustomCode.CompileTimeInject.Annotations; [Export(Lifetime.Scoped, ServiceId = ""1"")] public sealed class FirstFoo : IFoo { public string Id { get; } = ""1""; } }", @"namespace Demo.Domain { using CustomCode.CompileTimeInject.Annotations; [Export(Lifetime.Scoped, ServiceId = ""2"")] public sealed class SecondFoo : IFoo { public string Id { get; } = ""2""; } }"); var sourceGenerator = new ServiceFactoryGenerator(); var testEnvironment = CSharpGeneratorDriver.Create(sourceGenerator); // When testEnvironment.RunGeneratorsAndUpdateCompilation( compilation: input, outputCompilation: out var output, diagnostics: out var diagnostics); // Then Assert.False(diagnostics.HasErrors()); Assert.True(output.ContainsTypeWithMethodImplementation( "ServiceFactory", @"Demo.Domain.IFoo? INamedServiceFactory<Demo.Domain.IFoo>.CreateOrGetNamedService(string serviceId) { if (string.Equals(serviceId, ""1"", StringComparison.Ordinal)) { var service = (Demo.Domain.IFoo)ScopedInstances.GetOrAdd(typeof(Demo.Domain.IFoo), serviceId, _ => { var service = new Demo.Domain.FirstFoo(); return service; }); return service; } if (string.Equals(serviceId, ""2"", StringComparison.Ordinal)) { var service = (Demo.Domain.IFoo)ScopedInstances.GetOrAdd(typeof(Demo.Domain.IFoo), serviceId, _ => { var service = new Demo.Domain.SecondFoo(); return service; }); return service; } return default; }")); }
public void ImportNamedDependencyFactory() { // Given var input = CompilationBuilder.CreateAssemblyWithCode( @"namespace Demo.Domain { public interface IFoo { IBar Dependency { get; } } }", @"namespace Demo.Domain { public interface IBar { string Id { get; } } }", @"namespace Demo.Domain { using CustomCode.CompileTimeInject.Annotations; [Export] public sealed class Foo : IFoo { public Foo([Import(""1"")] Func<IBar> factory) { Dependency = factory(); } public IBar Dependency { get; } } }", @"namespace Demo.Domain { using CustomCode.CompileTimeInject.Annotations; [Export(ServiceId = ""1"")] public sealed class FirstBar : IBar { public string Id { get; } = ""1""; } }", @"namespace Demo.Domain { using CustomCode.CompileTimeInject.Annotations; [Export(ServiceId = ""2"")] public sealed class SecondBar : IBar { public string Id { get; } = ""2""; } }"); var sourceGenerator = new ServiceFactoryGenerator(); var testEnvironment = CSharpGeneratorDriver.Create(sourceGenerator); // When testEnvironment.RunGeneratorsAndUpdateCompilation( compilation: input, outputCompilation: out var output, diagnostics: out var diagnostics); // Then Assert.False(diagnostics.HasErrors()); Assert.True(output.ContainsTypeWithMethodImplementation( "ServiceFactory", @"Demo.Domain.IFoo IServiceFactory<Demo.Domain.IFoo>.CreateOrGetService() { var dependency1 = new Func<Demo.Domain.IBar>(((INamedServiceFactory<Demo.Domain.IBar>)this).CreateOrGetNamedService(""1"")); var service = new Demo.Domain.Foo(dependency1); return service; }")); }