Esempio n. 1
0
        public Assembly Build(HttpRequestHandlerDefinition[] definitions)
        {
            var references = new AssemblyReferencesHelper()
                             .AddReferenceForTypes(typeof(object), typeof(Controller), typeof(RequestHandlerControllerBuilder))
                             .AddReferenceForTypes(definitions.SelectMany(x => new[] { x.Definition.RequestType, x.Definition.ResponseType }).ToArray())
                             .GetReferences();

            var compilation = CSharpCompilation.Create(_assemblyName)
                              .WithOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary))
                              .AddReferences(references);
            var csharpControllers = new List <string>();
            var operationResults  = definitions.Select(temp => CreateCSharp(GetClassName(temp.Definition.RequestType), temp)).ToArray();
            var files             = new Dictionary <string, string>();

            files.Add("ProxyController", $@"namespace Proxy
{{
    public class ProxyController : {GetCorrectFormat(typeof(Controller))}
    {{
        private readonly {GetCorrectFormat(typeof(IWebRequestProcessor))} _requestProcessor;
        public ProxyController({GetCorrectFormat(typeof(IWebRequestProcessor))} requestProcessor)
        {{
            _requestProcessor = requestProcessor;
        }}

    {CodeStr.Foreach(operationResults.SelectMany(x => x.Operation.Split(new[] { Environment.NewLine }, StringSplitOptions.None)), operation => $@"
                      { operation } ")}
    }}
}}");
            foreach (var operationResult in operationResults)
            {
                files.Add(operationResult.OperationName, operationResult.RequestClass);
            }
            foreach (var temp in files)
            {
                compilation = compilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText(temp.Value));
            }
            var assemblyStream = new MemoryStream();
            var result         = compilation.Emit(assemblyStream);

            if (!result.Success)
            {
                var errormsg = new StringBuilder();
                foreach (var diagnostic in result.Diagnostics)
                {
                    errormsg.AppendLine(diagnostic.ToString());
                }
                throw new Exception(string.Join(Environment.NewLine, csharpControllers), new Exception(errormsg.ToString()));
            }
            assemblyStream.Seek(0, SeekOrigin.Begin);
            return(AssemblyLoadContext.Default.LoadFromStream(assemblyStream));
        }
        public OperationResult CreateCSharp(string operationName, HttpRequestHandlerDefinition builderDefinition,
                                            HashSet <string> uniqueClassNames)
        {
            var requestBodyProperties = builderDefinition.Parameters.Where(x => x.BindingType == BindingType.FromBody || x.BindingType == BindingType.FromForm).ToArray();
            var requestClass          = builderDefinition.Definition.RequestType.Name;
            var original = requestClass;
            var tryCount = 1;

            while (uniqueClassNames.Contains(requestClass))
            {
                requestClass = $"{original}_{++tryCount}";
            }

            var methodArgs = string.Join(",  ", builderDefinition.Parameters.GroupBy(x => x.PropertyName).Select(x => new
            {
                Name   = x.Key,
                Type   = x.First().BindingType == BindingType.FromBody || x.First().BindingType == BindingType.FromForm ? requestClass : GetCorrectFormat(x.First().PropertyInfo.PropertyType),
                Binder = x.First().BindingType
            }).Select(x => $"[Microsoft.AspNetCore.Mvc.{x.Binder}Attribute] {x.Type} {x.Name}"));
            var isAsync = builderDefinition.Definition.ResponseType.IsConstructedGenericType &&
                          builderDefinition.Definition.ResponseType.GetGenericTypeDefinition() == typeof(Task <>);
            var responseType = isAsync
                ? builderDefinition.Definition.ResponseType.GetGenericArguments()[0]
                : builderDefinition.Definition.ResponseType;
            var requestVariable = "request_" + Guid.NewGuid().ToString().Replace("-", "");
            var operationResult = new OperationResult();

            operationResult.OperationName = operationName;
            operationResult.RequestClass  = $@"public class {requestClass}
{{{CodeStr.Foreach(requestBodyProperties, source => $@"
    public {GetCorrectFormat(source.PropertyInfo.PropertyType)} {source.PropertyInfo.Name} {{ get; set; }}")}
}}";
            operationResult.Operation     = $@"{GetAttributes(builderDefinition.Definition)}[Microsoft.AspNetCore.Mvc.Http{builderDefinition.HttpMethod}Attribute(""{builderDefinition.Route}""), {GetCorrectFormat(typeof(ProducesAttribute))}(typeof({GetCorrectFormat(responseType)}))]
public  {(isAsync ? "async " : string.Empty)}{GetCorrectFormat(isAsync ? typeof(Task<IActionResult>) : typeof(IActionResult))} {operationName}({methodArgs})
{{
    var {requestVariable} = new {GetCorrectFormat(builderDefinition.Definition.RequestType)}
    {{{CodeStr.Foreach(builderDefinition.Parameters, assignment => $@"
        {assignment.PropertyInfo.Name} = {assignment.PropertyName}{(assignment.BindingType == BindingType.FromBody || assignment.BindingType == BindingType.FromForm ? $".{assignment.PropertyInfo.Name}" : "")},").Trim(',')}
    }};

    var response = {(isAsync ? "await " : string.Empty)}_requestProcessor.Process{(isAsync ? "Async" : string.Empty)}<{GetCorrectFormat(builderDefinition.Definition.RequestType)},{GetCorrectFormat(responseType)}>({requestVariable}, this);
    return response;
}}";
            return(operationResult);
        }