实现动态Controller插件化

using Hoa;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Emit;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;

namespace Proxy
{
    public class ProxyClass
    {
        /// <summary>
        /// 万能接口
        /// </summary>
        /// <param name="code">传入你要实现的代码</param>
        /// <returns>动态生成一个程序集</returns>
        public static Assembly GenerateProxyTree(string code)
        {
            Assembly assembly = null;
            SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(code);
            string assemblyName = "Hoa.Dynamic.WebApi";
            //var ass = AppGlobal.ApplicationAssembiles;
            var ass = new List<Assembly>();
            ass.Add(typeof(object).Assembly);
            //ass.Add(typeof(Attribute).Assembly);
            ass.Add(Assembly.Load("System.Runtime"));
            ass.AddRange(AppGlobal.ApplicationAssembiles);
            var references = ass.Select(x => MetadataReference.CreateFromFile(x.Location));
            CSharpCompilation compilation = CSharpCompilation.Create(assemblyName, new[] { syntaxTree }, references, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
            using (var ms = new MemoryStream())
            {
                EmitResult result = compilation.Emit(ms);
                if (result.Success)
                {
                    ms.Seek(0, SeekOrigin.Begin);
                    assembly = Assembly.Load(ms.ToArray());
                }
            }
            return assembly;
        }
    }
}
using Hoa.Dependencies;
using Hoa.ServiceController.Attributes;
using Microsoft.AspNetCore.Mvc;
using Proxy;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Hoa.Web.Host
{
    public static class AssClass
    {
        private static readonly Func<Assembly, IEnumerable<Type>> queryControllerTypesExp =
           ass => ass.GetTypes().Where(type => IsControllerType(type));

        private static bool IsControllerType(Type type)
        {
            if ((!type.IsInterface && !type.IsAbstract && !type.IsGenericType && type.IsPublic)
                && ((type.IsDefined(typeof(HoaServiceControllerAttribute))
                        && !type.IsDefined(typeof(HoaNonServiceWebApiAttribute))
                        && (
                            !type.IsDefined(typeof(ApiExplorerSettingsAttribute))
                            || (type.IsDefined(typeof(ApiExplorerSettingsAttribute)) && type.GetCustomAttribute<ApiExplorerSettingsAttribute>().IgnoreApi != true)
                        )
                        )
                )) return true;

            return false;
        }

        public static Assembly GetAss()
        {

            var stringBuilder = new StringBuilder();

            stringBuilder.AppendLine("namespace Hoa.Dynamic.WebApi");
            stringBuilder.AppendLine("{");

            var controllerTypes = AppGlobal.ApplicationAssembiles.SelectMany(queryControllerTypesExp);
            foreach (var serviceType in controllerTypes)
            {
                var serviceTypeInterface = serviceType.GetInterface($"I{serviceType.Name}", true);

                stringBuilder.AppendLine("[Hoa.ServiceController.Attributes.HoaServiceController]");
                stringBuilder.AppendLine($"public class HoaDynamic{serviceType.Name}: {typeof(IAppServiceDependency).FullName}");
                stringBuilder.AppendLine("{");
                stringBuilder.AppendLine($"private readonly {serviceTypeInterface.FullName} _service;");
                stringBuilder.AppendLine($"public HoaDynamic{serviceType.Name}({serviceTypeInterface.FullName} service)");
                stringBuilder.AppendLine("{");
                stringBuilder.AppendLine("_service = service;");
                stringBuilder.AppendLine("}");

                var methods = serviceType.GetMethods(BindingFlags.Instance | BindingFlags.Public).Where(u => u.DeclaringType == serviceType);
                foreach (var method in methods)
                {
                    var parameterDefines = string.Join(",", method.GetParameters().Select(u => $"{u.ParameterType.FullName} {u.Name}").ToArray());
                    var parameterDeliver = string.Join(",", method.GetParameters().Select(u => $"{u.Name}").ToArray());

                    stringBuilder.AppendLine($"public {(method.ReturnType == typeof(void) ? "void" : method.ReturnType.FullName)} {method.Name} ({parameterDefines})");
                    stringBuilder.AppendLine("{");
                    stringBuilder.AppendLine($"{(method.ReturnType == typeof(void) ? "" : "return")} _service.{method.Name}({parameterDeliver});");
                    stringBuilder.AppendLine("}");
                }

                stringBuilder.AppendLine("}");
            }

            stringBuilder.AppendLine("}");

            string code = stringBuilder.ToString();

            var ass = ProxyClass.GenerateProxyTree(code);
            return ass;
        }
    }
}

public void ConfigureServices(IServiceCollection services)
        {
            services.AddHoaServicesBefore(Configuration);
            services.AddControllers()
                .AddApplicationPart(AssClass.GetAss())
                .AddNewtonsoftJson();
            services.AddHoaServices();
        }
posted @ 2020-04-20 18:07  百小僧  阅读(734)  评论(1编辑  收藏  举报