コード例 #1
0
        public void CanReferenceOutputOfFirstGeneration()
        {
            var firstCode = @"public class MyClass
                   {
                       public void RunThings()
                       {
                           var y = 0;
                           var a = 1;
           
                           a = y + 10;
                       }
                   }";

            var firstGenerator = new CodeToAssemblyGenerator();
            var firstAssembly  = firstGenerator.GenerateAssembly(firstCode);

            var secondCode = @"public class AnotherClass
                   {
                       public void RunThings()
                       {
                           var y = new MyClass();
                           y.RunThings();
                       }
                   }";

            var secondGenerator = new CodeToAssemblyGenerator();

            secondGenerator.ReferenceAssembly(firstAssembly);

            var secondAssembly = secondGenerator.GenerateAssembly(secondCode);

            var type = secondAssembly.GetExportedTypes().Single();

            Assert.Equal("AnotherClass", type.Name);
        }
コード例 #2
0
        public void CanGenerateAssemblyFromCode()
        {
            var code = @"public class MyClass
                   {
                       public void RunThings()
                       {
                           var y = 0;
                           var a = 1;
           
                           a = y + 10;
                       }
                   }";

            var result = _generator.GenerateAssembly(code);

            var type = result.GetExportedTypes().Single();

            Assert.Equal("MyClass", type.Name);
        }
コード例 #3
0
        public Task <Assembly> CreateAssembly(AssemblyLoadContext loadContext)
        {
            try
            {
                var generator = new CodeToAssemblyGenerator();
                generator.ReferenceAssemblyContainingType <Action>();

                if (_options.AdditionalReferences?.Any() == true)
                {
                    foreach (var assembly in _options.AdditionalReferences)
                    {
                        generator.ReferenceAssembly(assembly);
                    }
                }

                var code = new StringBuilder();
                code.AppendLine("using System;");
                code.AppendLine("using System.Diagnostics;");
                code.AppendLine("using System.Threading.Tasks;");
                code.AppendLine("using System.Text;");
                code.AppendLine("using System.Collections;");
                code.AppendLine("using System.Collections.Generic;");

                if (_options.AdditionalNamespaces?.Any() == true)
                {
                    foreach (var ns in _options.AdditionalNamespaces)
                    {
                        code.AppendLine($"using {ns};");
                    }
                }

                code.AppendLine(_code);
                var assemblySourceCode = code.ToString();

                var result = generator.GenerateAssembly(assemblySourceCode, loadContext);

                return(Task.FromResult(result));
            }
            catch (Exception e)
            {
                throw new InvalidCodeException("Failed to create assembly from regular code. Code: " + _code, e);
            }
        }
コード例 #4
0
        public void CanWrapGeneratedType()
        {
            var code = @"namespace MyTest {
                   public class MyClass
                   {
                       public void RunThings()
                       {
                           var y = 0;
                           var a = 1;
           
                           a = y + 10;
                       }
                   }}";

            var generator = new CodeToAssemblyGenerator();
            var assembly  = generator.GenerateAssembly(code);

            var type = assembly.GetExportedTypes().Single();

            var wrapper = new TypeToTypeWrapper();

            var result = wrapper.CreateType(type,
                                            new TypeToTypeWrapperOptions()
            {
                IncludedProperties = new List <string>()
                {
                    "*"
                }, TypeName          = "WrappedType",
                AdditionalNamespaces = new List <string>()
                {
                    type.Namespace
                },
                AssemblyGenerator = generator
            });

            dynamic inst = Activator.CreateInstance(result);

            inst.RunThings();
        }
コード例 #5
0
        public async Task <Assembly> CreateAssembly(AssemblyLoadContext loadContext)
        {
            try
            {
                var returnType = await GetReturnType();

                var parameters = await GetParameters();

                var updatedScript = await RemoveProperties(_code);

                var generator = new CodeToAssemblyGenerator();
                generator.ReferenceAssemblyContainingType <Action>();

                var code = new StringBuilder();
                code.AppendLine("using System;");
                code.AppendLine("using System.Diagnostics;");
                code.AppendLine("using System.Threading.Tasks;");
                code.AppendLine("using System.Text;");
                code.AppendLine("using System.Collections;");
                code.AppendLine("using System.Collections.Generic;");
                code.AppendLine("using System.Reflection;");
                code.AppendLine("[assembly: AssemblyFileVersion(\"1.0.0.0\")]");

                if (_options.AdditionalNamespaces?.Any() == true)
                {
                    foreach (var ns in _options.AdditionalNamespaces)
                    {
                        code.AppendLine($"using {ns};");
                    }
                }

                code.AppendLine($"namespace {_options.NamespaceNameGenerator(_options)}");
                code.AppendLine("{");
                code.AppendLine($"public class {_options.TypeNameGenerator(_options)}");
                code.AppendLine("{");
                if (returnType == null)
                {
                    if (_options.ReturnsTask)
                    {
                        code.AppendLine($"public async Task {_options.MethodNameGenerator(_options)}({GetParametersString(parameters)})");
                    }
                    else
                    {
                        code.AppendLine($"public void {_options.MethodNameGenerator(_options)}({GetParametersString(parameters)})");
                    }
                }
                else
                {
                    if (_options.ReturnsTask)
                    {
                        code.AppendLine($"public async Task<{returnType.FullName}> {_options.MethodNameGenerator(_options)}({GetParametersString(parameters)})");
                    }
                    else
                    {
                        code.AppendLine($"public {returnType.FullName} {_options.MethodNameGenerator(_options)}({GetParametersString(parameters)})");
                    }
                }

                code.AppendLine("{"); // Start method
                code.AppendLine(updatedScript);
                code.AppendLine("}"); // End method
                code.AppendLine("}"); // End class
                code.AppendLine("}"); // End namespace

                var assemblySourceCode = code.ToString();

                var result = generator.GenerateAssembly(assemblySourceCode, loadContext);

                return(result);
            }
            catch (Exception e)
            {
                throw new InvalidCodeException("Failed to create assembly from script. Code: " + _code, e);
            }
        }
コード例 #6
0
        public Type CreateType(MulticastDelegate multicastDelegate,
                               DelegateToTypeWrapperOptions options = default)
        {
            var methodInfo = multicastDelegate.GetMethodInfo();

            if (methodInfo == null)
            {
                throw new Exception("Couldn't get method info from delegate");
            }

            var parameters = methodInfo.GetParameters();
            var returnType = methodInfo.ReturnType;

            var id = DelegateCache.Add(multicastDelegate);

            var allTypes = GetRequiredTypes(parameters, returnType);

            var generator = new CodeToAssemblyGenerator();

            AddReferences(generator, allTypes);

            var code = new StringBuilder();

            AddNamespaces(code, allTypes);

            var constructorParameterNames          = new List <string>();
            var methodParameterNamesWithTypes      = new List <string>();
            var constructorParameterNamesWithTypes = new List <string>();
            var constructorFielsNamesWithTypes     = new List <string>();
            var propertyNamesWithTypes             = new List <string>();
            var delegateMethodParameters           = new List <string>();

            var conversionRules = options?.ConversionRules;

            if (conversionRules == null)
            {
                conversionRules = new List <ParameterConversionRule>();
            }

            DoConversions(parameters, conversionRules, constructorParameterNames, constructorParameterNamesWithTypes, constructorFielsNamesWithTypes, delegateMethodParameters, propertyNamesWithTypes, methodParameterNamesWithTypes);

            code.AppendLine();
            code.AppendLine($"namespace {GetNamespace(options)}");
            code.AppendLine("{");
            code.AppendLine($"public class {GetTypeName(options)}");
            code.AppendLine("{");

            CreateConstructor(options, constructorParameterNames, constructorFielsNamesWithTypes, code, constructorParameterNamesWithTypes);
            CreateProperties(propertyNamesWithTypes, code);
            CreateDelegateWrapperMethod(options, returnType, code, methodParameterNamesWithTypes, id, delegateMethodParameters);

            code.AppendLine("}"); // Close class
            code.AppendLine("}"); // Close namespace

            var s        = code.ToString();
            var assembly = generator.GenerateAssembly(s);

            var result = assembly.GetExportedTypes().Single();

            return(result);
        }
コード例 #7
0
        public Type CreateType(Type originalType, TypeToTypeWrapperOptions options = default)
        {
            if (originalType == null)
            {
                throw new ArgumentNullException(nameof(originalType));
            }

            if (options == null)
            {
                options = new TypeToTypeWrapperOptions();
            }

            var methods = GetMethodsToWrap(originalType, options);

            var allTypes = new List <Type> {
                originalType
            };

            foreach (var methodInfo in methods)
            {
                var parameters = methodInfo.GetParameters();
                var returnType = methodInfo.ReturnType;

                var requiredTypesForMethod = GetRequiredTypes(parameters, returnType);

                foreach (var type in requiredTypesForMethod)
                {
                    if (allTypes.Contains(type))
                    {
                        continue;
                    }

                    allTypes.Add(type);
                }
            }

            var id = TypeCache.Add(originalType, options);

            var generator = new CodeToAssemblyGenerator();

            AddReferences(generator, allTypes, options, originalType);

            var code = new StringBuilder();

            AddNamespaces(code, allTypes);

            var constructorParameterNames          = new List <string>();
            var constructorParameterNamesWithTypes = new List <string>();
            var constructorFieldNamesWithTypes     = new List <string>();
            var propertyNamesWithTypes             = new List <string>();

            var conversionRules = options?.ConversionRules;

            if (conversionRules == null)
            {
                conversionRules = new List <ParameterConversionRule>();
            }

            var d = new Dictionary <MethodInfo, (List <string>, List <string>)>();

            foreach (var methodInfo in methods)
            {
                var parameters = methodInfo.GetParameters();

                var methodParameterNamesWithTypes = new List <string>();
                var delegateMethodParameters      = new List <string>();

                DoConversions(parameters, conversionRules, constructorParameterNames, constructorParameterNamesWithTypes, constructorFieldNamesWithTypes,
                              propertyNamesWithTypes, delegateMethodParameters, methodParameterNamesWithTypes, options, originalType);

                d.Add(methodInfo, (delegateMethodParameters, methodParameterNamesWithTypes));
            }

            if (options.AdditionalConstructorParameters?.Any() == true)
            {
                foreach (var additionalConstructorParameter in options.AdditionalConstructorParameters)
                {
                    AddConstructorParameter(additionalConstructorParameter, constructorParameterNames, constructorParameterNamesWithTypes,
                                            constructorFieldNamesWithTypes, options, originalType);
                }
            }

            code.AppendLine();
            code.AppendLine($"namespace {GetNamespace(options, originalType)}");
            code.AppendLine("{");


            var inheritedAndImplementedTypes = new List <Type>();

            if (options.Inherits != null)
            {
                inheritedAndImplementedTypes.Add(options.Inherits);
            }
            if (options.Implements != null)
            {
                inheritedAndImplementedTypes.AddRange(options.Implements);
            }

            var inheritance = "";

            if (inheritedAndImplementedTypes.Any())
            {
                inheritance = $" : {string.Join(", ", inheritedAndImplementedTypes.Select(x => x.FullName))}";
            }

            code.AppendLine($"public class {GetTypeName(options, originalType)} {inheritance}");
            code.AppendLine("{");

            CreateInstance(originalType, code, id);
            CreateConstructor(options, constructorParameterNames, constructorFieldNamesWithTypes, code, constructorParameterNamesWithTypes, originalType, id);
            CreateProperties(propertyNamesWithTypes, code);

            foreach (var methodInfo in methods)
            {
                var parameters = methodInfo.GetParameters();
                var returnType = methodInfo.ReturnType;

                var p = d[methodInfo];
                CreateWrapperMethod(options, returnType, code, p.Item2, id, p.Item1, methodInfo, originalType);
            }

            if (options.CustomCodeGenerator != null)
            {
                code.AppendLine("// Custom code begins");
                code.AppendLine(options.CustomCodeGenerator(options, originalType));
                code.AppendLine("// Custom code ends");
            }

            if (options.IsSourceCodeIncluded)
            {
                code.AppendLine("##sourceplaceholder##");
            }

            code.AppendLine("}"); // Close class
            code.AppendLine("}"); // Close namespace

            var fullCode = code.ToString();

            if (options.IsSourceCodePrettified)
            {
                fullCode = CSharpSyntaxTree.ParseText(fullCode).GetRoot().NormalizeWhitespace().ToFullString();
            }

            if (options.IsSourceCodeIncluded)
            {
                code.AppendLine("// Source code begins");
                fullCode = fullCode.Replace("##sourceplaceholder##", $"private string _source = @\"{Environment.NewLine}{fullCode.Replace("\"", "\"\"").Replace("##sourceplaceholder##", "")}\";");
                code.AppendLine("// Source code ends");
            }

            var assembly = generator.GenerateAssembly(fullCode);

            var result = assembly.GetExportedTypes().Single();

            return(result);
        }