一个简单的.net 6控制台程序框架

一个简单的.net 6控制台程序框架

其中包括,

1.使用IOC控制接口的生成,

2.使用OPtions来操作配置文件,

3.使用nlog来控制日志

4.自动获取所有的backgroundService并运行

源码:

https://gitee.com/gamov/Net6ConsoleProgram

1. Program.cs

using System.Reflection;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using NLog.Extensions.Logging;
using Stee.FGMS.ACOS.Tools.WsServerSimulator.Frame.Attributes;
using Stee.FGMS.ACOS.Tools.WsServerSimulator.Services.Statics;

var builder = new HostBuilder().ConfigureHostConfiguration(builder =>
{
    builder.AddInMemoryCollection(new Dictionary<string, string>
    {
        [HostDefaults.EnvironmentKey] = Environment.GetEnvironmentVariable("DOTNETCORE_ENVIRONMENT"),
    });
}).ConfigureAppConfiguration((hostContext, configApp) =>
{
    var env = hostContext.HostingEnvironment;
    configApp.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
          .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true);
}).ConfigureServices((hostContext, services) =>
{
    var types = Assembly.GetExecutingAssembly().GetTypes();
    var descriptors = new List<ServiceDescriptor>();
    var hostServiceTypes = new List<Type>();
    var optionTypes = new List<(Type, string)>();

    foreach (var type in types)
    {
        var attr = type.GetCustomAttribute<ComponentAttribute>();
        if (attr != null)
        {
            descriptors.Add(new ServiceDescriptor(attr.InterfaceType, type, attr.LifeTime));
        }

        var attr1 = type.GetCustomAttribute<HostServiceAttribute>();
        if (attr1 != null)
        {
            hostServiceTypes.Add(type);
        }

        var attr2 = type.GetCustomAttribute<OptionAttribute>();
        if (attr2 != null)
        {
            optionTypes.Add((type, attr2.RootName));
        }
    }

    foreach (var item in descriptors)
    {
        // 依赖注入
        services.Add(item);
    }

    foreach (var optionType in optionTypes)
    {
        // 反射绑定配置文件,等价于services.AddOptions<ServerConfig>().Bind(hostContext.Configuration.GetSection("Server"));
        var result = CommonReflects.OptionsServiceCollectionExtensions_AddOptions(optionType.Item1)
            .Invoke(services, new object[] { services });
        CommonReflects.OptionsBuilderConfigurationExtensions_Bind(optionType.Item1)
            .Invoke(result, new object[] { result, hostContext.Configuration.GetSection(optionType.Item2) });
    }

    foreach (var hostServiceType in hostServiceTypes)
    {
        // 反射获取hostservice, 等价于 services.AddHostedService<WebsocketServerHost>();
        CommonReflects.ServiceCollectionHostedServiceExtensions_AddHostedService(hostServiceType).Invoke(services, new object[] { services });
    }

    services.AddLogging(builder =>
    {
        builder.SetMinimumLevel(LogLevel.Trace);
        builder.AddNLog(hostContext.Configuration);
    });
}).UseConsoleLifetime();

await builder.Build().RunAsync();

 

2. 必要的3个特性(attribute)

ComponentAttribute标记需要放入容器管理的服务

public class ComponentAttribute : Attribute
{
    public ComponentAttribute(Type interfaceType, ServiceLifetime lifeTime = ServiceLifetime.Scoped)
    {
        InterfaceType = interfaceType;
        LifeTime = lifeTime;
    }
    
    public Type InterfaceType { get; set; }
    public ServiceLifetime LifeTime { get; set; }
}

 

HostServiceAttribute标记需要后台运行的backgroundService

public class HostServiceAttribute : Attribute
{
}

 

OptionAttribute标记需要读取配置到Options的内容

public class OptionAttribute : Attribute
{
    public OptionAttribute(string rootName)
    {
        RootName = rootName;
    }

    public string RootName { get; set; }
}

 

3.必要的静态方法

反射运行一些方法

public static class CommonReflects
{
    public static MethodInfo OptionsServiceCollectionExtensions_AddOptions(Type genericType)
    {
        var method1 = typeof(OptionsServiceCollectionExtensions).GetMethod("AddOptions", 1, new Type[] { typeof(IServiceCollection) });
        method1 = method1.MakeGenericMethod(genericType);
        return method1;
    }

    public static MethodInfo OptionsBuilderConfigurationExtensions_Bind(Type genericType)
    {
        var method1 = typeof(OptionsBuilderConfigurationExtensions).GetMethods().First(a => a.Name == "Bind" && a.GetParameters().Count() == 2);
        method1 = method1.MakeGenericMethod(genericType);
        return method1;
    }

    public static MethodInfo ServiceCollectionHostedServiceExtensions_AddHostedService(Type genericType)
    {
        var method = typeof(ServiceCollectionHostedServiceExtensions).GetMethod("AddHostedService", new Type[] { typeof(IServiceCollection) });
        method = method.MakeGenericMethod(genericType);
        return method;
    }

}

 

使用该框架就可以使用基本的IOC来运行.net6的控制台程序。

posted @ 2023-02-06 12:03  N伽莫夫J  阅读(447)  评论(0编辑  收藏  举报