Uragano.DynamicProxy
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;
}
}
}