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<TReceivePackage> : HostBuilderAdapter<SuperSocketHostBuilder<TReceivePackage>>, ISuperSocketHostBuilder<TReceivePackage>, IHostBuilder
{
private Func<HostBuilderContext, IConfiguration, IConfiguration> _serverOptionsReader;
protected List<Action<HostBuilderContext, IServiceCollection>> ConfigureServicesActions { get; private set; } = new List<Action<HostBuilderContext, IServiceCollection>>();
protected List<Action<HostBuilderContext, IServiceCollection>> ConfigureSupplementServicesActions = new List<Action<HostBuilderContext, IServiceCollection>>();
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<TReceivePackage> ConfigureSupplementServices(Action<HostBuilderContext, IServiceCollection> configureDelegate)
{
ConfigureSupplementServicesActions.Add(configureDelegate);
return this;
}
ISuperSocketHostBuilder ISuperSocketHostBuilder.ConfigureSupplementServices(Action<HostBuilderContext, IServiceCollection> 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<ServerOptions>(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<IPackageDecoder<StringPackageInfo>, DefaultStringPackageDecoder>());
}
services.TryAdd(ServiceDescriptor.Singleton<IPackageEncoder<string>, 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<TReceivePackage>).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<SuperSocketService<TReceivePackage>>(servicesInHost);
}
protected virtual void RegisterHostedService<THostedService>(IServiceCollection servicesInHost)
where THostedService : class, IHostedService
{
servicesInHost.AddSingleton<THostedService, THostedService>();
servicesInHost.AddSingleton<IServerInfo>(s => s.GetService<THostedService>() as IServerInfo);
servicesInHost.AddHostedService<THostedService>(s => s.GetService<THostedService>());
}
public ISuperSocketHostBuilder<TReceivePackage> ConfigureServerOptions(Func<HostBuilderContext, IConfiguration, IConfiguration> serverOptionsReader)
{
_serverOptionsReader = serverOptionsReader;
return this;
}
ISuperSocketHostBuilder<TReceivePackage> ISuperSocketHostBuilder<TReceivePackage>.ConfigureServices(Action<HostBuilderContext, IServiceCollection> configureDelegate)
{
return ConfigureServices(configureDelegate);
}
public override SuperSocketHostBuilder<TReceivePackage> ConfigureServices(Action<HostBuilderContext, IServiceCollection> configureDelegate)
{
ConfigureServicesActions.Add(configureDelegate);
return this;
}
public virtual ISuperSocketHostBuilder<TReceivePackage> UsePipelineFilter<TPipelineFilter>()
where TPipelineFilter : IPipelineFilter<TReceivePackage>, new()
{
return this.ConfigureServices((ctx, services) =>
{
services.AddSingleton<IPipelineFilterFactory<TReceivePackage>, DefaultPipelineFilterFactory<TReceivePackage, TPipelineFilter>>();
});
}
public virtual ISuperSocketHostBuilder<TReceivePackage> UsePipelineFilterFactory<TPipelineFilterFactory>()
where TPipelineFilterFactory : class, IPipelineFilterFactory<TReceivePackage>
{
return this.ConfigureServices((ctx, services) =>
{
services.AddSingleton<IPipelineFilterFactory<TReceivePackage>, TPipelineFilterFactory>();
});
}
public virtual ISuperSocketHostBuilder<TReceivePackage> UseSession<TSession>()
where TSession : IAppSession
{
return this.UseSessionFactory<GenericSessionFactory<TSession>>();
}
public virtual ISuperSocketHostBuilder<TReceivePackage> UseSessionFactory<TSessionFactory>()
where TSessionFactory : class, ISessionFactory
{
return this.ConfigureServices(
(hostCtx, services) =>
{
services.AddSingleton<ISessionFactory, TSessionFactory>();
}
);
}
public virtual ISuperSocketHostBuilder<TReceivePackage> UseHostedService<THostedService>()
where THostedService : class, IHostedService
{
if (!typeof(SuperSocketService<TReceivePackage>).IsAssignableFrom(typeof(THostedService)))
{
throw new ArgumentException($"The type parameter should be subclass of {nameof(SuperSocketService<TReceivePackage>)}", nameof(THostedService));
}
return this.ConfigureServices((ctx, services) =>
{
RegisterHostedService<THostedService>(services);
});
}
public virtual ISuperSocketHostBuilder<TReceivePackage> UsePackageDecoder<TPackageDecoder>()
where TPackageDecoder : class, IPackageDecoder<TReceivePackage>
{
return this.ConfigureServices(
(hostCtx, services) =>
{
services.AddSingleton<IPackageDecoder<TReceivePackage>, TPackageDecoder>();
}
);
}
public virtual ISuperSocketHostBuilder<TReceivePackage> UseMiddleware<TMiddleware>()
where TMiddleware : class, IMiddleware
{
return this.ConfigureServices((ctx, services) =>
{
services.TryAddEnumerable(ServiceDescriptor.Singleton<IMiddleware, TMiddleware>());
});
}
public ISuperSocketHostBuilder<TReceivePackage> UsePackageHandlingScheduler<TPackageHandlingScheduler>()
where TPackageHandlingScheduler : class, IPackageHandlingScheduler<TReceivePackage>
{
return this.ConfigureServices(
(hostCtx, services) =>
{
services.AddSingleton<IPackageHandlingScheduler<TReceivePackage>, TPackageHandlingScheduler>();
}
);
}
public ISuperSocketHostBuilder<TReceivePackage> UsePackageHandlingContextAccessor()
{
return this.ConfigureServices(
(hostCtx, services) =>
{
services.AddSingleton<IPackageHandlingContextAccessor<TReceivePackage>, PackageHandlingContextAccessor<TReceivePackage>>();
}
);
}
}
public static class SuperSocketHostBuilder
{
public static ISuperSocketHostBuilder<TReceivePackage> Create<TReceivePackage>()
where TReceivePackage : class
{
return Create<TReceivePackage>(args: null);
}
public static ISuperSocketHostBuilder<TReceivePackage> Create<TReceivePackage>(string[] args)
{
return new SuperSocketHostBuilder<TReceivePackage>(args);
}
public static ISuperSocketHostBuilder<TReceivePackage> Create<TReceivePackage, TPipelineFilter>()
where TPipelineFilter : IPipelineFilter<TReceivePackage>, new()
{
return Create<TReceivePackage, TPipelineFilter>(args: null);
}
public static ISuperSocketHostBuilder<TReceivePackage> Create<TReceivePackage, TPipelineFilter>(string[] args)
where TPipelineFilter : IPipelineFilter<TReceivePackage>, new()
{
return new SuperSocketHostBuilder<TReceivePackage>(args)
.UsePipelineFilter<TPipelineFilter>();
}
}
}