using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;
using SuperSocket;
using SuperSocket.ProtoBase;
using SuperSocket.Server;
namespace SuperSocket
{
public class SuperSocketHostBuilder : HostBuilderAdapter>, ISuperSocketHostBuilder, IHostBuilder
{
private Func _serverOptionsReader;
protected List> ConfigureServicesActions { get; private set; } = new List>();
protected List> ConfigureSupplementServicesActions = new List>();
public SuperSocketHostBuilder(IHostBuilder hostBuilder)
: base(hostBuilder)
{
}
public SuperSocketHostBuilder()
: this(args: null)
{
}
public SuperSocketHostBuilder(string[] args)
: base(args)
{
}
public override IHost Build()
{
return HostBuilder.ConfigureServices((ctx, services) =>
{
RegisterBasicServices(ctx, services, services);
}).ConfigureServices((ctx, services) =>
{
foreach (var action in ConfigureServicesActions)
{
action(ctx, services);
}
foreach (var action in ConfigureSupplementServicesActions)
{
action(ctx, services);
}
}).ConfigureServices((ctx, services) =>
{
RegisterDefaultServices(ctx, services, services);
}).Build();
}
public ISuperSocketHostBuilder ConfigureSupplementServices(Action configureDelegate)
{
ConfigureSupplementServicesActions.Add(configureDelegate);
return this;
}
ISuperSocketHostBuilder ISuperSocketHostBuilder.ConfigureSupplementServices(Action configureDelegate)
{
return ConfigureSupplementServices(configureDelegate);
}
protected virtual void RegisterBasicServices(HostBuilderContext builderContext, IServiceCollection servicesInHost, IServiceCollection services)
{
var serverOptionReader = _serverOptionsReader;
if (serverOptionReader == null)
{
serverOptionReader = (ctx, config) =>
{
return config;
};
}
services.AddOptions();
var config = builderContext.Configuration.GetSection("serverOptions");
var serverConfig = serverOptionReader(builderContext, config);
services.Configure(serverConfig);
}
protected virtual void RegisterDefaultServices(HostBuilderContext builderContext, IServiceCollection servicesInHost, IServiceCollection services)
{
// if the package type is StringPackageInfo
if (typeof(TReceivePackage) == typeof(StringPackageInfo))
{
services.TryAdd(ServiceDescriptor.Singleton, DefaultStringPackageDecoder>());
}
services.TryAdd(ServiceDescriptor.Singleton, DefaultStringEncoderForDI>());
// if no host service was defined, just use the default one
if (!CheckIfExistHostedService(services))
{
RegisterDefaultHostedService(servicesInHost);
}
}
protected virtual bool CheckIfExistHostedService(IServiceCollection services)
{
return services.Any(s => s.ServiceType == typeof(IHostedService)
&& typeof(SuperSocketService).IsAssignableFrom(GetImplementationType(s)));
}
private Type GetImplementationType(ServiceDescriptor serviceDescriptor)
{
if (serviceDescriptor.ImplementationType != null)
return serviceDescriptor.ImplementationType;
if (serviceDescriptor.ImplementationInstance != null)
return serviceDescriptor.ImplementationInstance.GetType();
if (serviceDescriptor.ImplementationFactory != null)
{
var typeArguments = serviceDescriptor.ImplementationFactory.GetType().GenericTypeArguments;
if (typeArguments.Length == 2)
return typeArguments[1];
}
return null;
}
protected virtual void RegisterDefaultHostedService(IServiceCollection servicesInHost)
{
RegisterHostedService>(servicesInHost);
}
protected virtual void RegisterHostedService(IServiceCollection servicesInHost)
where THostedService : class, IHostedService
{
servicesInHost.AddSingleton();
servicesInHost.AddSingleton(s => s.GetService() as IServerInfo);
servicesInHost.AddHostedService(s => s.GetService());
}
public ISuperSocketHostBuilder ConfigureServerOptions(Func serverOptionsReader)
{
_serverOptionsReader = serverOptionsReader;
return this;
}
ISuperSocketHostBuilder ISuperSocketHostBuilder.ConfigureServices(Action configureDelegate)
{
return ConfigureServices(configureDelegate);
}
public override SuperSocketHostBuilder ConfigureServices(Action configureDelegate)
{
ConfigureServicesActions.Add(configureDelegate);
return this;
}
public virtual ISuperSocketHostBuilder UsePipelineFilter()
where TPipelineFilter : IPipelineFilter, new()
{
return this.ConfigureServices((ctx, services) =>
{
services.AddSingleton, DefaultPipelineFilterFactory>();
});
}
public virtual ISuperSocketHostBuilder UsePipelineFilterFactory()
where TPipelineFilterFactory : class, IPipelineFilterFactory
{
return this.ConfigureServices((ctx, services) =>
{
services.AddSingleton, TPipelineFilterFactory>();
});
}
public virtual ISuperSocketHostBuilder UseSession()
where TSession : IAppSession
{
return this.UseSessionFactory>();
}
public virtual ISuperSocketHostBuilder UseSessionFactory()
where TSessionFactory : class, ISessionFactory
{
return this.ConfigureServices(
(hostCtx, services) =>
{
services.AddSingleton();
}
);
}
public virtual ISuperSocketHostBuilder UseHostedService()
where THostedService : class, IHostedService
{
if (!typeof(SuperSocketService).IsAssignableFrom(typeof(THostedService)))
{
throw new ArgumentException($"The type parameter should be subclass of {nameof(SuperSocketService)}", nameof(THostedService));
}
return this.ConfigureServices((ctx, services) =>
{
RegisterHostedService(services);
});
}
public virtual ISuperSocketHostBuilder UsePackageDecoder()
where TPackageDecoder : class, IPackageDecoder
{
return this.ConfigureServices(
(hostCtx, services) =>
{
services.AddSingleton, TPackageDecoder>();
}
);
}
public virtual ISuperSocketHostBuilder UseMiddleware()
where TMiddleware : class, IMiddleware
{
return this.ConfigureServices((ctx, services) =>
{
services.TryAddEnumerable(ServiceDescriptor.Singleton());
});
}
public ISuperSocketHostBuilder UsePackageHandlingScheduler()
where TPackageHandlingScheduler : class, IPackageHandlingScheduler
{
return this.ConfigureServices(
(hostCtx, services) =>
{
services.AddSingleton, TPackageHandlingScheduler>();
}
);
}
public ISuperSocketHostBuilder UsePackageHandlingContextAccessor()
{
return this.ConfigureServices(
(hostCtx, services) =>
{
services.AddSingleton, PackageHandlingContextAccessor>();
}
);
}
}
public static class SuperSocketHostBuilder
{
public static ISuperSocketHostBuilder Create()
where TReceivePackage : class
{
return Create(args: null);
}
public static ISuperSocketHostBuilder Create(string[] args)
{
return new SuperSocketHostBuilder(args);
}
public static ISuperSocketHostBuilder Create()
where TPipelineFilter : IPipelineFilter, new()
{
return Create(args: null);
}
public static ISuperSocketHostBuilder Create(string[] args)
where TPipelineFilter : IPipelineFilter, new()
{
return new SuperSocketHostBuilder(args)
.UsePipelineFilter();
}
}
}