csharp/1100100/Uragano/src/Uragano.DynamicProxy/ServiceBuilder.cs

ServiceBuilder.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Uragano.Abstractions;
using Uragano.Abstractions.Service;

namespace Uragano.DynamicProxy
{
    public clast ServiceBuilder : IHostedService
    {
        private IServiceFactory ServiceFactory { get; }

        private IServiceProvider ServiceProvider { get; }

        private UraganoSettings UraganoSettings { get; }


        public ServiceBuilder(IServiceFactory serviceFactory, IServiceProvider serviceProvider, UraganoSettings uraganoSettings)
        {
            ServiceFactory = serviceFactory;
            ServiceProvider = serviceProvider;
            UraganoSettings = uraganoSettings;
        }

        private static bool IsImplementationMethod(MethodInfo serviceMethod, MethodInfo implementationMethod)
        {
            return serviceMethod.Name == implementationMethod.Name &&
                   serviceMethod.ReturnType == implementationMethod.ReturnType &&
                   serviceMethod.ContainsGenericParameters == implementationMethod.ContainsGenericParameters &&
                   SameParameters(serviceMethod.GetParameters(), implementationMethod.GetParameters());
        }

        private static bool SameParameters(IReadOnlyCollection parameters1, IReadOnlyList parameters2)
        {
            if (parameters1.Count == parameters2.Count)
            {
                return !parameters1.Where((t, i) => t.ParameterType != parameters2[i].ParameterType || t.IsOptional != parameters2[i].IsOptional || t.Position != parameters2[i].Position || t.HasDefaultValue != parameters2[i].HasDefaultValue).Any();
            }
            return false;
        }


        public async Task StartAsync(CancellationToken cancellationToken)
        {
            UraganoSettings.ClientGlobalInterceptors.Reverse();
            UraganoSettings.ServerGlobalInterceptors.Reverse();

            var enableClient = ServiceProvider.GetService() != null;
            var enableServer = UraganoSettings.ServerSettings != null;

            var types = ReflectHelper.GetDependencyTypes();
            var services = types.Where(t => t.IsInterface && typeof(IService).IsastignableFrom(t)).Select(@interface => new
            {
                Interface = @interface,
                Implementation = types.FirstOrDefault(p => p.IsClast && p.IsPublic && !p.IsAbstract && !p.Name.EndsWith("_____UraganoClientProxy") && @interface.IsastignableFrom(p))
            }).ToList();

            foreach (var service in services)
            {
                var imp = service.Implementation;

                var routeAttr = service.Interface.GetCustomAttribute();
                var routePrefix = routeAttr == null ? $"{service.Interface.Namespace}/{service.Interface.Name}" : routeAttr.Route;


                var interfaceMethods = service.Interface.GetMethods();

                List implementationMethods = null;
                if (enableServer && imp != null)
                    implementationMethods = imp.GetMethods().ToList();

                var disableClientIntercept = service.Interface.GetCustomAttribute(true) != null;
                var clientClastInterceptors = new List();
                if (!disableClientIntercept)
                    clientClastInterceptors = service.Interface.GetCustomAttributes(true).Where(p => p is IInterceptor)
                    .Select(p => p.GetType()).ToList();

                var serverClastInterceptors = new List();
                var disableServerIntercept = false;
                if (enableServer && imp != null)
                {
                    disableServerIntercept = imp.GetCustomAttribute(true) != null;
                    if (!disableServerIntercept)
                        serverClastInterceptors = imp.GetCustomAttributes(true).Where(p => p is IInterceptor)
                            .Select(p => p.GetType()).ToList();
                }

                foreach (var interfaceMethod in interfaceMethods)
                {
                    MethodInfo serverMethod = null;
                    var idAttr = interfaceMethod.GetCustomAttribute();
                    var route = idAttr == null ? $"{routePrefix}/{interfaceMethod.Name}" : $"{routePrefix}/{idAttr.Route}";

                    var clientInterceptors = new List();
                    if (enableClient && !disableClientIntercept && interfaceMethod.GetCustomAttribute(true) == null)
                    {
                        clientInterceptors.AddRange(UraganoSettings.ClientGlobalInterceptors);
                        clientInterceptors.AddRange(clientClastInterceptors);
                        clientInterceptors.AddRange(interfaceMethod.GetCustomAttributes(true)
                            .Where(p => p is IInterceptor).Select(p => p.GetType()).ToList());
                        clientInterceptors.Reverse();
                    }


                    var serverInterceptors = new List();
                    if (enableServer && imp != null)
                    {
                        serverMethod = implementationMethods.First(p => IsImplementationMethod(interfaceMethod, p));
                        if (!disableServerIntercept && serverMethod?.GetCustomAttribute(true) == null)
                        {
                            serverInterceptors.AddRange(UraganoSettings.ServerGlobalInterceptors);
                            serverInterceptors.AddRange(serverClastInterceptors.ToList());
                            if (serverMethod != null)
                                serverInterceptors.AddRange(serverMethod.GetCustomAttributes(true)
                                    .Where(p => p is IInterceptor).Select(p => p.GetType()).ToList());
                            serverInterceptors.Reverse();
                        }
                    }

                    ServiceFactory.Create(route, serverMethod, interfaceMethod, serverInterceptors, clientInterceptors);
                }
            }

            await Task.CompletedTask;
        }

        public async Task StopAsync(CancellationToken cancellationToken)
        {
            await Task.CompletedTask;
        }
    }
}