{"id":16640000,"url":"https://github.com/luoyunchong/sampleapp","last_synced_at":"2025-10-30T09:30:59.342Z","repository":{"id":102902182,"uuid":"366040030","full_name":"luoyunchong/SampleApp","owner":"luoyunchong","description":"Console,xUnit,aspnetcore  集成DI,Autofac,Serilog,FreeSql,HttpClient,JWT等组件示例","archived":false,"fork":false,"pushed_at":"2023-12-11T08:21:38.000Z","size":116,"stargazers_count":13,"open_issues_count":0,"forks_count":7,"subscribers_count":3,"default_branch":"master","last_synced_at":"2023-12-11T09:31:52.255Z","etag":null,"topics":["console","di","freesql","serilog","xunit"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/luoyunchong.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2021-05-10T12:46:26.000Z","updated_at":"2023-08-16T02:59:27.000Z","dependencies_parsed_at":"2023-12-11T09:31:25.955Z","dependency_job_id":"5f096803-766e-41fa-bc5c-3720ccded0c2","html_url":"https://github.com/luoyunchong/SampleApp","commit_stats":null,"previous_names":[],"tags_count":0,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luoyunchong%2FSampleApp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luoyunchong%2FSampleApp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luoyunchong%2FSampleApp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/luoyunchong%2FSampleApp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/luoyunchong","download_url":"https://codeload.github.com/luoyunchong/SampleApp/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":219856489,"owners_count":16556082,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["console","di","freesql","serilog","xunit"],"created_at":"2024-10-12T07:07:36.300Z","updated_at":"2025-10-30T09:30:54.004Z","avatar_url":"https://github.com/luoyunchong.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n\n## SampleApp\n\nConsole集成依赖注入，Serilog日志\n\n技术要点\n\n- Scriban\n- HTTP Request\n- Serilog\n- Humanizer\n- HtmlAgilityPack\n- FreeSql\n- Newtonsoft.Json\n- Json Web Token\n\nxUnit集成依赖注入\n\n- Xunit.DependencyInjection\n\n## 新建一个console项目\n\n引用包\n```xml\n\u003cPackageReference Include=\"Microsoft.Extensions.Hosting\" Version=\"7.0.1\" /\u003e\n```\n\n初始化Host\n```csharp\nstatic IHost AppStartup()\n{\n    var host = Host.CreateDefaultBuilder() // Initialising the Host \n                .ConfigureServices((context, services) =\u003e\n                {\n                    // Adding the DI container for configuration\n                    services.AddTransient\u003cApp\u003e(); // Add transiant mean give me an instance each it is being requested\n                })\n                .ConfigureAppConfiguration((host, config) =\u003e\n                {\n                    //config.AddJsonFile($\"settings.json\", optional: true, reloadOnChange: true);\n                })\n                .Build(); // Build the Host\n\n    return host;\n}\n```\n\n一个简单的服务，没有接口\n```csharp\npublic class App\n{\n    private readonly ILogger\u003cApp\u003e _logger;\n    public App(ILogger\u003cApp\u003e logger)\n    {\n        _logger = logger;\n    }\n\n    public async Task RunAsync(string[] args)\n    {\n        _logger.LogInformation(\"App Run Start\");\n        await Task.FromResult(0);\n        _logger.LogInformation(\"App Run End!\");\n    }\n}\n```\n\n调用 \n```csharp\nstatic async Task Main(string[] args)\n{\n    var host = AppStartup();\n\n    var app = host.Services.GetService\u003cApp\u003e();\n\n    await app.RunAsync(args);\n}\n```\n\n\n### 集成 Serilog\n\n引用包\n```xml\n\u003cPackageReference Include=\"Serilog.Extensions.Hosting\" Version=\"4.1.2\" /\u003e\n\u003cPackageReference Include=\"Serilog.Settings.Configuration\" Version=\"3.2.0\" /\u003e\n\u003cPackageReference Include=\"Serilog.Sinks.Console\" Version=\"4.0.0\" /\u003e\n\u003cPackageReference Include=\"Serilog.Sinks.File\" Version=\"5.0.0\" /\u003e\n```\n\n\n在Build方法调用 之前调用 `UseSerilog`\n```diff\nstatic IHost AppStartup()\n{\n    var host = Host.CreateDefaultBuilder() // Initialising the Host \n                .ConfigureServices((context, services) =\u003e\n                {\n                    // Adding the DI container for configuration\n                    ConfigureServices(context, services);\n                    services.AddTransient\u003cApp\u003e(); // Add transiant mean give me an instance each it is being requested\n                })\n                .ConfigureAppConfiguration((host, config) =\u003e\n                {\n                    config.AddJsonFile($\"settings.json\", optional: true, reloadOnChange: true);\n                })\n+                .UseSerilog() // Add Serilog\n                .Build(); // Build the Host\n\n    return host;\n}\n```\n\n\n增加一个单独的方法配置服务\n```csharp\nstatic void ConfigureServices(HostBuilderContext context, IServiceCollection services)\n{\n    var configuration = context.Configuration;\n\n    Log.Logger = new LoggerConfiguration() // initiate the logger configuration\n                    .ReadFrom.Configuration(configuration) // connect serilog to our configuration folder\n                    .Enrich.FromLogContext() //Adds more information to our logs from built in Serilog \n                    .CreateLogger(); //initialise the logger\n\n    Log.Logger.Information(\"ConfigureServices Starting\");\n\n}\n```  \n\nappsettings.json中配置\n```json\n   \"Serilog\": {\n    \"Using\": [\n      \"Serilog.Sinks.Console\",\n      \"Serilog.Sinks.File\"\n    ],\n    \"MinimalLevel\": {\n      \"Default\": \"Information\",\n      \"Override\": {\n        \"Microsoft\": \"Information\",\n        \"System\": \"Information\"\n      }\n    },\n    \"WriteTo\": [\n      {\n        \"Name\": \"File\",\n        \"Args\": {\n          \"path\": \"Logs/log.txt\",\n          \"rollingInterval\": \"Day\"\n        }\n      },\n      {\n        \"Name\": \"Console\",\n        \"Args\": {\n          \"theme\": \"Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console\",\n          \"outputTemplate\": \"[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj} \u003cs:{SourceContext}\u003e{NewLine}{Exception}\"\n        }\n      }\n    ]\n  },\n```\n\n\n## 发送HTTP请求\n\n增加包\n\n```xml\n    \u003cPackageReference Include=\"Microsoft.Extensions.Http\" Version=\"5.0.0\" /\u003e\n```\n \n在ConfigureServices增加配置服务项\n\n```csharp\n    services.AddHttpClient();\n```    \n       \n在App.cs中就可以调用了\n\n```csharp\npublic class App\n{\n    private readonly ILogger\u003cApp\u003e _logger;\n    private readonly IHttpClientFactory httpClientFactory;\n    public App(ILogger\u003cApp\u003e loggerIHttpClientFactory httpClientFactory)\n    {\n        _logger = logger;\n        this.httpClientFactory = httpClientFactory;\n    }\n    public async Task\u003cT\u003e GetAsync\u003cT\u003e(string url)\n    {\n        Dictionary\u003cstring, string\u003e headers = new Dictionary\u003cstring, string\u003e\n        {\n{\"accept\", \"application/json, text/plain, */*\"},\n{\"Accept-Language\", \"zh-CN,zh;q=0.9\" },\n{\"Cookie\", \"\"},\n{ \"Proxy-Connection\",\" keep-alive\"},\n{\"Upgrade-Insecure-Requests\", \"1\"},\n{\"User-Agent\", \"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36\"}\n        };\n\n        using (HttpClient client = httpClientFactory.CreateClient())\n        {\n            if (headers != null)\n            {\n                foreach (var header in headers)\n                    client.DefaultRequestHeaders.Add(header.Key, header.Value);\n            }\n            T result = default(T);\n            var response = await client.GetAsync(url);\n            if (response.IsSuccessStatusCode)\n            {\n                result = await response.Content.ReadFromJsonAsync\u003cT\u003e();\n            }\n\n            return result;\n        }\n    }\n}\n```\n\n## 集成 FreeSql\n\n引用包\n```xml\n\t\u003cPackageReference Include=\"FreeSql\" Version=\"2.6.100\" /\u003e\n\t\u003cPackageReference Include=\"FreeSql.Provider.Sqlite\" Version=\"2.6.100\" /\u003e\n\t\u003cPackageReference Include=\"FreeSql.Provider.MySqlConnector\" Version=\"2.6.100\" /\u003e\n\t\u003cPackageReference Include=\"FreeSql.Provider.SqlServer\" Version=\"2.6.100\" /\u003e\n\t\u003cPackageReference Include=\"FreeSql.Repository\" Version=\"2.6.100\" /\u003e\n```\n\n \n在方法ConfigureServices配置FreeSql的服务\n```csharp\nstatic void ConfigureServices(HostBuilderContext context, IServiceCollection services)\n{\n    IFreeSql fsql = new FreeSql.FreeSqlBuilder()\n                        //.UseConnectionString(FreeSql.DataType.Sqlite, configuration[\"ConnectionStrings:DefaultConnection\"])\n                        .UseConnectionString(FreeSql.DataType.MySql, configuration[\"ConnectionStrings:MySql\"])\n                        //.UseConnectionString(FreeSql.DataType.SqlServer, configuration[\"ConnectionStrings:SqlServer\"])\n                        .UseAutoSyncStructure(true)\n                        //.UseNoneCommandParameter(true)\n                        //.UseGenerateCommandParameterWithLambda(true)\n                        .UseLazyLoading(true)\n                        .UseMonitorCommand(\n                            cmd =\u003e Trace.WriteLine(\"\\r\\n线程\" + Thread.CurrentThread.ManagedThreadId + \": \" + cmd.CommandText)\n                            )\n                        .Build();\n    fsql.Aop.ConfigEntityProperty += (s, e) =\u003e\n    {\n        if (e.Property.PropertyType == typeof(decimal) || e.Property.PropertyType == typeof(decimal?))\n        {\n            e.ModifyResult.Precision = 18;\n            e.ModifyResult.Scale = 6;\n            e.ModifyResult.DbType = \"decimal\";\n        }\n    };\n\n    services.AddSingleton(fsql);\n    services.AddFreeRepository();\n    services.AddScoped\u003cUnitOfWorkManager\u003e();\n}\n```\n\nappsettings.json配置数据库链接\n```json\n \"ConnectionStrings\": {\n    \"DefaultConnection\": \"Data Source=|DataDirectory|\\\\SampleApp.db;\",\n    \"MySql\": \"Data Source=localhost;Port=3306;User ID=root;Password=root;Initial Catalog=sampleapp;Charset=utf8mb4;SslMode=none;Max pool size=1;Connection LifeTime=20\",\n    \"SqlServer\": \"Data Source=192.168.1.19;User Id=sa;Password=123456;Initial Catalog=freesqlTest;Pooling=true;Min Pool Size=1\"\n  },\n```\n\n\n强类型绑定对象\n```csharp\n    services.Configure\u003cAppOption\u003e(configuration.GetSection(nameof(AppOption)));\n```\n\n实体\n```csharp\npublic class AppOption\n{\n    public string TemplatesPath { get; set; }\n    public string OutputDirectory { get; set; }\n}\n```\n\nappsettings.json配置json对象\n```json\n \"AppOption\": {\n    \"TemplatesPath\": \"./Templates\", //相对路径，当前项目下的Templates目录\n    \"OutputDirectory\": \"../../../Output\" //可以是相对路径，也可以是绝对路径\n  }\n```\n\n\n使用\n```csharp\npublic class App\n{\n    private readonly ILogger\u003cApp\u003e _logger;\n    private readonly AppOption _appOption;\n    public App(ILogger\u003cApp\u003e logger, IOptions\u003cAppOption\u003e appOption)\n    {\n        _logger = logger;\n        _appOption = appOption.Value;\n    }\n}\n```\n\n\n爬虫`HtmlAgilityPack`，Josn序列化`Newtonsoft.Json`，友好的帮助类`Humanizer`，模板引擎`Scriban`\n```xml\n\t\u003cPackageReference Include=\"HtmlAgilityPack\" Version=\"1.11.36\" /\u003e\n\t\u003cPackageReference Include=\"Newtonsoft.Json\" Version=\"13.0.1\" /\u003e\n\t\u003cPackageReference Include=\"Humanizer.Core\" Version=\"2.11.10\" /\u003e\n\t\u003cPackageReference Include=\"Scriban\" Version=\"4.0.1\" /\u003e\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fluoyunchong%2Fsampleapp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fluoyunchong%2Fsampleapp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fluoyunchong%2Fsampleapp/lists"}