一、
Main 函数体
Log.Logger = new LoggerConfiguration()
#if DEBUG
.MinimumLevel.Debug()
.WriteTo.Console()
#else
.MinimumLevel.Information()
.MinimumLevel.Override("Microsoft", LogEventLevel.Warning)
.MinimumLevel.Override("System", LogEventLevel.Warning)
.Enrich.FromLogContext()
.WriteTo.Logger(l =>
l.Filter.ByIncludingOnly(e => e.Level == LogEventLevel.Error)
.WriteTo.File(new CompactJsonFormatter(), "log/err-.log", rollingInterval: RollingInterval.Hour, rollOnFileSizeLimit: true, fileSizeLimitBytes: 1000 * 1000))
.WriteTo.Logger(l =>
l.Filter.ByIncludingOnly(e => e.Level == LogEventLevel.Warning)
.WriteTo.File(new CompactJsonFormatter(), "log/wrn-.log", rollingInterval: RollingInterval.Hour, rollOnFileSizeLimit: true, fileSizeLimitBytes: 1000 * 1000))
.WriteTo.Logger(l =>
l.Filter.ByIncludingOnly(e => e.Level == LogEventLevel.Information)
.WriteTo.File(new CompactJsonFormatter(), "log/inf-.log", rollingInterval: RollingInterval.Hour, rollOnFileSizeLimit: true, fileSizeLimitBytes: 1000 * 1000))
#endif
.CreateLogger();
Log.Logger.Warning("configure serilog");
// build configuration
var configuration = new ConfigurationBuilder()
.AddEnvironmentVariables("")
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", false)
.Build();
Log.Logger.Warning("build configuration");
// setup DI
var services = new ServiceCollection()
.AddLogging(loggingBuilder => loggingBuilder.AddSerilog(dispose: true))
.AddSingleton<IConfiguration>(configuration)
.AddMemoryCache()
.AddSingleton(new RedisHelper(configuration[""], configuration[""], int.Parse(configuration[""])));
// 注册数据库访问类
services.RegisterDbContextCollection(configuration, Directory.GetCurrentDirectory(), "Impl.dll");
var serviceProvider = services.BuildServiceProvider();
// 可读取类
serviceProvider.GetRequiredService<class>()
//读取接口
serviceProvider.GetServices<interface>()
二、
/// 基于上面代码对ioc IServiceCollection 的扩展
public static class ServiceCollectionExtension
{
private static readonly Dictionary<string, Assembly> AssemblyCache = new Dictionary<string, Assembly>();
public static IServiceCollection AddSingletons<TInterface>(this IServiceCollection services,
string path, string pathSearchPattern, SearchOption searchOption = SearchOption.AllDirectories)
where TInterface : class
{
var iTaskExecutorType = typeof(TInterface);
bool Predicate(Type t)
{
return iTaskExecutorType != t && iTaskExecutorType.IsAssignableFrom(t);
}
var files = new DirectoryInfo(path).GetFileSystemInfos(pathSearchPattern, searchOption);
foreach (var file in files)
{
if (!AssemblyCache.ContainsKey(file.FullName))
AssemblyCache.Add(file.FullName, AssemblyLoadContext.Default.LoadFromAssemblyPath(file.FullName));
var assembly = AssemblyCache[file.FullName];
if (assembly != null)
foreach (var item in assembly.GetExportedTypes().Where(Predicate))
if (!item.IsAbstract)
services.AddSingleton(iTaskExecutorType, item);
}
return services;
}
public static IServiceCollection RegisterDbContextCollection(this IServiceCollection services,
IConfiguration configuration,
string path, string pathSearchPattern, SearchOption searchOption = SearchOption.AllDirectories)
{
bool Predicate(Type t)
{
return t.GetMethod("RegisterType") != null;
}
var files = new DirectoryInfo(path).GetFileSystemInfos(pathSearchPattern, searchOption);
foreach (var file in files)
{
if (!AssemblyCache.ContainsKey(file.FullName))
AssemblyCache.Add(file.FullName, AssemblyLoadContext.Default.LoadFromAssemblyPath(file.FullName));
var assembly = AssemblyCache[file.FullName];
if (assembly != null)
foreach (var item in assembly.GetExportedTypes().Where(Predicate))
if (item.IsAbstract)
item.GetMethod("RegisterType").Invoke(null, new object[] { services, configuration });
}
return services;
}
/// <summary>
/// 注册任务类
/// </summary>
/// <param name="services"></param>
/// <param name="configuration"></param>
/// <param name="path"></param>
/// <param name="pathSearchPattern"></param>
/// <param name="searchOption"></param>
/// <returns></returns>
public static IServiceCollection RegisterImplServiceCollection(this IServiceCollection services, IConfiguration configuration,
string path, string pathSearchPattern, SearchOption searchOption = SearchOption.AllDirectories)
{
bool Predicate(Type t)
{
return t.GetMethod("Services") != null;
}
var files = new DirectoryInfo(path).GetFileSystemInfos(pathSearchPattern, searchOption);
foreach (var file in files)
{
if (!AssemblyCache.ContainsKey(file.FullName))
AssemblyCache.Add(file.FullName, AssemblyLoadContext.Default.LoadFromAssemblyPath(file.FullName));
var assembly = AssemblyCache[file.FullName];
if (assembly != null)
foreach (var item in assembly.GetExportedTypes().Where(Predicate))
if (item.IsAbstract)
item.GetMethod("Services").Invoke(null, new object[] { services, configuration });
}
return services;
}
}
三、
/// 基于第二个图的扩展注册-委托调用查找的方法注册。
/// 认真看下第二个应该能理解
/// <summary>
/// 注册服务
/// </summary>
public static class RegisterImplService
{
public static IServiceCollection RegisterImplServices(this IServiceCollection services, IConfiguration configuration)
{
// 可以随意注册要使用的类和接口
if (configuration.GetSection("").Exists())
{
var config = configuration.GetSection("").Get<class>();
services.AddSingleton(config);
services.AddSingleton<Cache>();
}
return services;
}
}