示例#1
0
        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);
                 }"));
        }
示例#5
0
        /// <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);
            }
        }
示例#6
0
        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()}");
            }
        }
示例#11
0
        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;
                 }"));
        }