예제 #1
0
        public OperationResult CreateCSharp(string operationName, HttpRequestHandlerDefinition builderDefinition)
        {
            var requestBodyProperties = builderDefinition.Parameters.Where(x => x.BindingType == BindingType.FromBody || x.BindingType == BindingType.FromForm).ToArray();
            var requestClass          = builderDefinition.Definition.RequestType.Name + "_" + Guid.NewGuid().ToString().Replace("-", "");


            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 == BindingType.FromBody ? "FromBody" : "FromUri",
                BindingType = x.First().BindingType
            }).Select(x => $"[System.Web.Http.{x.Binder}Attribute] {x.Type} {x.Name}{CodeStr.If(x.BindingType == BindingType.FromQuery, $" = default({x.Type})")}"));
            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     = $@"[System.Web.Http.Http{builderDefinition.HttpMethod}Attribute, {GetCorrectFormat(typeof(RouteAttribute))}(""{ builderDefinition.Route}""), {GetCorrectFormat(typeof(ResponseTypeAttribute))}(typeof({GetCorrectFormat(responseType)}))]
public  {(isAsync ? "async " : string.Empty)}{GetCorrectFormat(isAsync ? typeof(Task<IHttpActionResult>) : typeof(IHttpActionResult))} {operationName}({methodArgs})
{{
    var {requestVariable} = new {GetCorrectFormat(builderDefinition.Definition.RequestType)}();{CodeStr.Foreach(builderDefinition.Parameters, assignment => $@"
    {requestVariable}.{assignment.PropertyInfo.Name} = {assignment.PropertyName}{(assignment.BindingType == BindingType.FromBody || assignment.BindingType == BindingType.FromForm ? $".{assignment.PropertyInfo.Name}" : "")};")}

    var response = {(isAsync ? "await " : string.Empty)}_requestProcessor.Process{(isAsync ? "Async" : string.Empty)}<{GetCorrectFormat(builderDefinition.Definition.RequestType)},{GetCorrectFormat(responseType)}>({requestVariable}, this);
    return response;
}}";
            return(operationResult);
        }
예제 #2
0
        public Assembly Build(HttpRequestHandlerDefinition[] definitions)
        {
            var references = new AssemblyReferencesHelper()
                             .AddReferenceForTypes(typeof(object), typeof(ApiController), typeof(RequestHandlerControllerBuilder))
                             .AddReferenceForTypes(GetType())
                             .AddReferenceForTypes(definitions.SelectMany(x => new[] { x.Definition.RequestType, x.Definition.ResponseType }).ToArray())
                             .GetReferences();

            var compilation = CSharpCompilation.Create(_assemblyName)
                              .WithOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
                                           .WithOptimizationLevel(_debug ? OptimizationLevel.Debug : OptimizationLevel.Release))
                              .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
{{{CodeStr.If(!string.IsNullOrEmpty(_options.RoutePrefix), $@"
    [{GetCorrectFormat(typeof(RoutePrefixAttribute))}(""{_options.RoutePrefix}"")]")}{CodeStr.Foreach(_options?.ControllerAttributeTypes, x => $@"
    [{GetCorrectFormat(x)}]")}
    public class ProxyController : {GetCorrectFormat(typeof(ApiController))}
    {{
        private readonly {GetCorrectFormat(typeof(IWebApiRequestProcessor))} _requestProcessor;
        public ProxyController({GetCorrectFormat(typeof(IWebApiRequestProcessor))} 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)
            {
                if (_debug)
                {
                    var filePath = Path.Combine(Path.GetTempPath(), $"rc_{temp.Key}.cs");
                    File.WriteAllText(filePath, temp.Value, Encoding.UTF8);
                    compilation =
                        compilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText(temp.Value, path: filePath,
                                                                              encoding: Encoding.UTF8));
                }
                else
                {
                    compilation = compilation.AddSyntaxTrees(CSharpSyntaxTree.ParseText(temp.Value));
                }
            }

            if (!_debug)
            {
                var assemblyStream = new MemoryStream();
                var result         = compilation.Emit(assemblyStream);
                CheckCompilationForErrors(result, csharpControllers);
                assemblyStream.Seek(0, SeekOrigin.Begin);
                return(Assembly.Load(assemblyStream.ToArray()));
            }
            else
            {
                var assemblyStream = new MemoryStream();
                var pdbStream      = new MemoryStream();
                var result         = compilation.Emit(assemblyStream, pdbStream);
                CheckCompilationForErrors(result, csharpControllers);
                assemblyStream.Seek(0, SeekOrigin.Begin);
                pdbStream.Seek(0, SeekOrigin.Begin);
                var rawAssembly = assemblyStream.ToArray();
                return(Assembly.Load(rawAssembly, pdbStream.ToArray()));
            }
        }