{"id":138,"date":"2022-08-24T19:42:22","date_gmt":"2022-08-24T11:42:22","guid":{"rendered":"https:\/\/miie.net\/?p=138"},"modified":"2022-08-24T19:42:22","modified_gmt":"2022-08-24T11:42:22","slug":"ultimate-asp-net-core-web-api-chapter2-configuring-a-logging-service","status":"publish","type":"post","link":"https:\/\/diji.net\/?p=138","title":{"rendered":"Chapter2:CONFIGURING A LOGGING SERVICE"},"content":{"rendered":"<h1>2 Configuring a Logging Service<\/h1>\n<p>Why does logging messages matter so much during application development? While our application is in the development stage, it's easy to debug the code and find out what happened. But debugging in a production environment is not that easy.<br \/>\n\u4e3a\u4ec0\u4e48\u5728\u5e94\u7528\u7a0b\u5e8f\u5f00\u53d1\u8fc7\u7a0b\u4e2d\u8bb0\u5f55\u6d88\u606f\u5982\u6b64\u91cd\u8981\uff1f\u867d\u7136\u6211\u4eec\u7684\u5e94\u7528\u7a0b\u5e8f\u5904\u4e8e\u5f00\u53d1\u9636\u6bb5\uff0c\u4f46\u5f88\u5bb9\u6613\u8c03\u8bd5\u4ee3\u7801\u5e76\u627e\u51fa\u53d1\u751f\u4e86\u4ec0\u4e48\u3002\u4f46\u662f\u5728\u751f\u4ea7\u73af\u5883\u4e2d\u8fdb\u884c\u8c03\u8bd5\u5e76\u4e0d\u5bb9\u6613\u3002\u200c\u200c<\/p>\n<p>That's why log messages are a great way to find out what went wrong and why and where the exceptions have been thrown in our code in the production environment. Logging also helps us more easily follow the flow of our application when we don\u2019t have access to the debugger.<br \/>\n\u8fd9\u5c31\u662f\u4e3a\u4ec0\u4e48\u65e5\u5fd7\u6d88\u606f\u662f\u627e\u51fa\u95ee\u9898\u6240\u5728\u4ee5\u53ca\u4e3a\u4ec0\u4e48\u4ee5\u53ca\u5728\u751f\u4ea7\u73af\u5883\u4e2d\u7684\u4ee3\u7801\u4e2d\u629b\u51fa\u5f02\u5e38\u7684\u539f\u56e0\u548c\u4f4d\u7f6e\u7684\u597d\u65b9\u6cd5\u3002\u65e5\u5fd7\u8bb0\u5f55\u8fd8\u6709\u52a9\u4e8e\u6211\u4eec\u5728\u65e0\u6cd5\u8bbf\u95ee\u8c03\u8bd5\u5668\u65f6\u66f4\u8f7b\u677e\u5730\u8ddf\u8e2a\u5e94\u7528\u7a0b\u5e8f\u7684\u6d41\u7a0b\u3002<\/p>\n<p>.NET Core has its own implementation of the logging mechanism, but in all our projects we prefer to create our custom logger service with the external logger library NLog.<br \/>\n.NET Core \u6709\u81ea\u5df1\u7684\u65e5\u5fd7\u8bb0\u5f55\u673a\u5236\u5b9e\u73b0\uff0c\u4f46\u5728\u6211\u4eec\u6240\u6709\u7684\u9879\u76ee\u4e2d\uff0c\u6211\u4eec\u66f4\u559c\u6b22\u4f7f\u7528\u5916\u90e8\u8bb0\u5f55\u5668\u5e93 NLog \u521b\u5efa\u81ea\u5b9a\u4e49\u8bb0\u5f55\u5668\u670d\u52a1\u3002<\/p>\n<p>That is exactly what we are going to do in this chapter.<br \/>\n\u8fd9\u6b63\u662f\u6211\u4eec\u5c06\u5728\u672c\u7ae0\u4e2d\u8981\u505a\u7684\u3002<\/p>\n<h2>2.1 Creating the Required Projects<\/h2>\n<p>Let\u2019s create two new projects. In the first one named <strong>Contracts<\/strong>, we are going to keep our interfaces. We will use this project later on too, to define our contracts for the whole application. The second one, <strong>LoggerService<\/strong>, we are going to use to write our logger logic in.<br \/>\n\u8ba9\u6211\u4eec\u521b\u5efa\u4e24\u4e2a\u65b0\u9879\u76ee\u3002\u5728\u7b2c\u4e00\u4e2a\u540d\u4e3a<strong>Contracts<\/strong>\uff0c\u6211\u4eec\u5c06\u4fdd\u7559\u6211\u4eec\u7684\u63a5\u53e3\u3002\u6211\u4eec\u7a0d\u540e\u4e5f\u5c06\u4f7f\u7528\u6b64\u9879\u76ee\u6765\u5b9a\u4e49\u6574\u4e2a\u5e94\u7528\u7a0b\u5e8f\u7684\u534f\u5b9a\u3002\u7b2c\u4e8c\u4e2a\u662f <strong>LoggerService<\/strong> \uff0c\u6211\u4eec\u5c06\u7528\u5b83\u6765\u7f16\u5199\u6211\u4eec\u7684\u8bb0\u5f55\u5668\u903b\u8f91\u3002<\/p>\n<p>To create a new project, right-click on the solution window, choose Add and then NewProject. Choose the Class Library (.NET Core) project:<br \/>\n\u82e5\u8981\u521b\u5efa\u65b0\u9879\u76ee\uff0c\u8bf7\u53f3\u952e\u5355\u51fb\u89e3\u51b3\u65b9\u6848\u7a97\u53e3\uff0c\u9009\u62e9\u201c\u6dfb\u52a0\u201d\uff0c\u7136\u540e\u9009\u62e9\u201c\u65b0\u5efa\u9879\u76ee\u201d\u3002\u9009\u62e9\u201c\u7c7b\u5e93\uff08.NET Core\uff09\u201d\u9879\u76ee\uff1a<\/p>\n<p><img decoding=\"async\" src=\"\/img\/20220824-ultimate-asp-net-core-web-api\/Image_2001.jpg\" alt=\"alt\" \/><\/p>\n<p>Finally, name it <strong>Contracts.<\/strong> Do the same thing for the second project and name it <strong>LoggerService<\/strong>. Now that we have these projects in place, we need to reference them from our main project.<br \/>\n\u6700\u540e\uff0c\u5c06\u5176\u547d\u540d\u4e3a <strong>Contracts<\/strong> \u3002\u5bf9\u7b2c\u4e8c\u4e2a\u9879\u76ee\u6267\u884c\u76f8\u540c\u7684\u64cd\u4f5c\uff0c\u5e76\u5c06\u5176\u547d\u540d\u4e3a <strong>LoggerService<\/strong> \u3002\u73b0\u5728\u6211\u4eec\u5df2\u7ecf\u6709\u4e86\u8fd9\u4e9b\u9879\u76ee\uff0c\u6211\u4eec\u9700\u8981\u4ece\u6211\u4eec\u7684\u4e3b\u9879\u76ee\u4e2d\u5f15\u7528\u5b83\u4eec\u3002<\/p>\n<p>To do that, navigate to the solution explorer. Then in the <strong>LoggerService<\/strong> project, right-click on <strong>Dependencies<\/strong> and choose the <strong>AddReference<\/strong> option. Under Projects, click Solution and check the <strong>Contracts<\/strong> project.<br \/>\n\u4e3a\u6b64\uff0c\u8bf7\u5bfc\u822a\u5230\u89e3\u51b3\u65b9\u6848\u8d44\u6e90\u7ba1\u7406\u5668\u3002\u7136\u540e\u5728 L<strong>oggerService<\/strong> \u9879\u76ee\u4e2d\uff0c\u53f3\u952e\u5355\u51fb\u201c\u4f9d\u8d56\u9879\u201d\u5e76\u9009\u62e9\u201c\u6dfb\u52a0\u5f15\u7528\u201d\u9009\u9879\u3002\u5728\u201c\u9879\u76ee\u201d\u4e0b\uff0c\u5355\u51fb\u201c\u89e3\u51b3\u65b9\u6848\u201d\u5e76\u9009\u4e2d\u201c<strong>Contracts<\/strong>\u201d\u9879\u76ee\u3002<\/p>\n<p>Now, in the main project right click on <strong>Dependencies<\/strong> and then click on <strong>Add Reference<\/strong>. Check the <strong>LoggerService<\/strong> checkbox to import it. Since we have referenced the <strong>Contracts<\/strong> project through the <strong>LoggerService<\/strong>, it will be available in the main project too.<br \/>\n\u73b0\u5728\uff0c\u5728\u4e3b\u9879\u76ee\u4e2d\uff0c\u53f3\u952e\u5355\u51fb\u201c\u4f9d\u8d56\u9879\u201d\uff0c\u7136\u540e\u5355\u51fb\u201c\u6dfb\u52a0\u5f15\u7528\u201d\u3002\u9009\u4e2d\u201c <strong>LoggerService<\/strong> \u201d\u590d\u9009\u6846\u4ee5\u5c06\u5176\u5bfc\u5165\u3002\u7531\u4e8e\u6211\u4eec\u5df2\u7ecf\u901a\u8fc7<strong>LoggerService<\/strong>\u5f15\u7528\u4e86<strong>Contracts<\/strong>\u9879\u76ee\uff0c\u56e0\u6b64\u5b83\u4e5f\u5c06\u5728\u4e3b\u9879\u76ee\u4e2d\u63d0\u4f9b\u3002<\/p>\n<h2>2.2 Creating the lLoggerManager Interface and Installing Nlog<\/h2>\n<p>Our logger service will contain four methods for logging our messages:<br \/>\n\u6211\u4eec\u7684\u8bb0\u5f55\u5668\u670d\u52a1\u5c06\u5305\u542b\u56db\u79cd\u7528\u4e8e\u8bb0\u5f55\u6d88\u606f\u7684\u65b9\u6cd5\uff1a<\/p>\n<ul>\n<li>Info messages \u4fe1\u606f\u6d88\u606f<\/li>\n<li>Debug messages\u8c03\u8bd5\u6d88\u606f<\/li>\n<li>Warning messages\u8b66\u544a\u6d88\u606f<\/li>\n<li>Error messages\u9519\u8bef\u6d88\u606f<\/li>\n<\/ul>\n<p>To achieve this, we are going to create an interface named <strong>ILoggerManager<\/strong> inside the <strong>Contracts<\/strong> project containing those four method definitions.<br \/>\n\u4e3a\u4e86\u5b9e\u73b0\u8fd9\u4e00\u70b9\uff0c\u6211\u4eec\u5c06\u521b\u5efa\u4e00\u4e2a\u63a5\u53e3\u3002\u5728\u5305\u542b\u8fd9\u56db\u4e2a\u65b9\u6cd5\u5b9a\u4e49\u7684 <strong>Contracts<\/strong> \u9879\u76ee\u4e2d\u547d\u540d\u4e3a <strong>ILoggerManager<\/strong>\u3002<\/p>\n<p>So, let\u2019s do that first:<br \/>\n\u6240\u4ee5\uff0c\u8ba9\u6211\u4eec\u5148\u8fd9\u6837\u505a\uff1a<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nnamespace Contracts\n{\n    public interface ILoggerManager\n    {\n        void LogInfo(string message);\n        void LogWarn(string message);\n        void LogDebug(string message);\n        void LogError(string message);\n    }\n}\n<\/pre>\n<p>Before we implement this interface inside the <strong>LoggerService<\/strong> project, we need to install the <strong>NLog<\/strong> library in our <strong>LoggerService<\/strong> project. <strong>NLog<\/strong> is a logging platform for .NET which will help us create and log our messages.<br \/>\n\u5728 <strong>LoggerService<\/strong> \u9879\u76ee\u4e2d\u5b9e\u73b0\u6b64\u63a5\u53e3\u4e4b\u524d\uff0c\u6211\u4eec\u9700\u8981\u5728 <strong>LoggerService<\/strong> \u9879\u76ee\u4e2d\u5b89\u88c5 <strong>NLog<\/strong> \u5e93\u3002<strong>NLog<\/strong>\u662f.NET\u7684\u65e5\u5fd7\u8bb0\u5f55\u5e73\u53f0\uff0c\u5b83\u5c06\u5e2e\u52a9\u6211\u4eec\u521b\u5efa\u548c\u8bb0\u5f55\u6d88\u606f\u3002<\/p>\n<p>We are going to show two different ways of adding the <strong>NLog<\/strong> library to our project.<br \/>\n\u6211\u4eec\u5c06\u5c55\u793a\u5c06 <strong>NLog<\/strong> \u5e93\u6dfb\u52a0\u5230\u9879\u76ee\u4e2d\u7684\u4e24\u79cd\u4e0d\u540c\u65b9\u6cd5\u3002<\/p>\n<p>1.In the <strong>LoggerService<\/strong> project, right-click on the <strong>Dependencies<\/strong> and choose Manage NuGet Packages. After the <strong>NuGet Package Manager<\/strong> window appears, just follow these steps:<br \/>\n\u5728 <strong>LoggerService<\/strong> \u9879\u76ee\u4e2d\uff0c\u53f3\u952e\u5355\u51fb\u201c\u4f9d\u8d56\u9879\u201d\uff0c\u7136\u540e\u9009\u62e9\u201c\u7ba1\u7406 NuGet \u5305\u201d\u3002\u51fa\u73b0\u201cNuGet \u5305\u7ba1\u7406\u5668\u201d\u7a97\u53e3\u540e\uff0c\u53ea\u9700\u6267\u884c\u4ee5\u4e0b\u6b65\u9aa4\uff1a<\/p>\n<p><img decoding=\"async\" src=\"\/img\/20220824-ultimate-asp-net-core-web-api\/Image_2002.jpg\" alt=\"alt\" \/><\/p>\n<p>2.From the View menu, choose Other Windows and then click on the <strong>Package Manager Console<\/strong>. After the console appears, type: Install-Package NLog.Extensions.Logging -Version 1.6.5<br \/>\n\u4ece\u201c\u89c6\u56fe\u201d\u83dc\u5355\u4e2d\uff0c\u9009\u62e9\u201c\u5176\u4ed6\u7a97\u53e3\u201d\uff0c\u7136\u540e\u5355\u51fb\u201c\u7a0b\u5e8f\u5305\u7ba1\u7406\u5668\u63a7\u5236\u53f0\u201d\u3002\u63a7\u5236\u53f0\u51fa\u73b0\u540e\uff0c\u952e\u5165\uff1a<br \/>\nInstall-Package NLog.Extensions.Logging -Version 1.6.5<\/p>\n<p>After a couple of seconds, <strong>NLog<\/strong> is up and running in our application.<br \/>\n\u51e0\u79d2\u949f\u540e\uff0c<strong>NLog<\/strong> \u5728\u6211\u4eec\u7684\u5e94\u7528\u7a0b\u5e8f\u4e2d\u542f\u52a8\u5e76\u8fd0\u884c\u3002<\/p>\n<h2>2.3  Implementing the Interface and Nlog.Config File<\/h2>\n<p>In the <strong>LoggerService<\/strong> project, we are going to create a new class: <strong>LoggerManager<\/strong>. Now let\u2019s have it implement the <strong>ILoggerManager<\/strong> interface we previously defined:<br \/>\n\u5728 <strong>LoggerService<\/strong> \u9879\u76ee\u4e2d\uff0c\u6211\u4eec\u5c06\u521b\u5efa\u4e00\u4e2a\u65b0\u7684\u7c7b\uff1a<strong>LoggerManager<\/strong>\u3002\u73b0\u5728\u8ba9\u6211\u4eec\u8ba9\u5b83\u5b9e\u73b0<strong>ILoggerManager<\/strong>\u6211\u4eec\u4e4b\u524d\u5b9a\u4e49\u7684\u63a5\u53e3\uff1a<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\nusing Contracts;\nusing NLog;\nnamespace LoggerService\n{\n    public class LoggerManager : ILoggerManager\n    {\n        private static ILogger logger = LogManager.GetCurrentClassLogger();\n        public LoggerManager()\n        {\n        }\n        public void LogDebug(string message)\n        {\n            logger.Debug(message);\n        }\n        public void LogError(string message)\n        {\n            logger.Error(message);\n        }\n        public void LogInfo(string message)\n        {\n            logger.Info(message);\n        }\n        public void LogWarn(string message)\n        {\n            logger.Warn(message);\n        }\n    }\n}\n<\/pre>\n<p>As you can see, our methods are just wrappers around NLog\u2019s methods. Both <strong>ILogger<\/strong> and <strong>LogManager<\/strong> are part of the <strong>NLog<\/strong> namespace. Now, we need to configure it and inject it into the Startup class in the <strong>ConfigureServices<\/strong> method.<br \/>\n\u5982\u60a8\u6240\u89c1\uff0c\u6211\u4eec\u7684\u65b9\u6cd5\u53ea\u662f\u56f4\u7ed5NLog\u65b9\u6cd5\u7684\u5305\u88c5\u5668\u3002<strong>ILogger<\/strong> \u548c <strong>LogManager<\/strong> \u90fd\u662f <strong>NLog<\/strong> \u547d\u540d\u7a7a\u95f4\u7684\u4e00\u90e8\u5206\u3002\u73b0\u5728\uff0c\u6211\u4eec\u9700\u8981\u914d\u7f6e\u5b83\u5e76\u5c06\u5176\u6ce8\u5165\u5230 Startup \u7c7b\u4e2d<strong>ConfigureServices<\/strong> \u65b9\u6cd5\u3002<\/p>\n<p>NLog needs to have information about where to put log files on the file system, what the name of these files will be, and what is the minimum level of logging that we want.<br \/>\nNLog \u9700\u8981\u5305\u542b\u6709\u5173\u5c06\u65e5\u5fd7\u6587\u4ef6\u653e\u5728\u6587\u4ef6\u7cfb\u7edf\u4e0a\u7684\u4f4d\u7f6e\u3001\u8fd9\u4e9b\u6587\u4ef6\u7684\u540d\u79f0\u4ee5\u53ca\u6211\u4eec\u60f3\u8981\u7684\u6700\u4f4e\u65e5\u5fd7\u8bb0\u5f55\u7ea7\u522b\u7684\u4fe1\u606f\u3002<\/p>\n<p>We are going to define all these constants in a text file in the main project and name it <strong>nlog.config<\/strong>. You'll need to change the path of the <strong>internal log<\/strong> and <strong>filename<\/strong> parameters to your own paths.<br \/>\n\u6211\u4eec\u5c06\u5728\u4e3b\u9879\u76ee\u7684\u4e00\u4e2a\u6587\u672c\u6587\u4ef6\u4e2d\u5b9a\u4e49\u6240\u6709\u8fd9\u4e9b\u5e38\u91cf\uff0c\u5e76\u5c06\u5176\u547d\u540d\u4e3a<strong>nlog.config<\/strong>\u3002\u60a8\u9700\u8981\u66f4\u6539 <strong>internal log\u8def\u5f84<\/strong> \u548c <strong>filename<\/strong> \u53c2\u6570\u5230\u60a8\u81ea\u5df1\u7684\u8def\u5f84\u3002<\/p>\n<p><pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n&lt;?xml version=&quot;1.0&quot; encoding=&quot;utf-8&quot; ?&gt;\n&lt;nlog xmlns=&quot;http:\/\/www.nlog-project.org\/schemas\/NLog.xsd&quot; \n      xmlns:xsi=&quot;http:\/\/www.w3.org\/2001\/XMLSchema-instance&quot; \n      autoReload=&quot;true&quot; internalLogLevel=&quot;Trace&quot; \n      internalLogFile=&quot;d:\\Projects\\CompanyEmployees\\Project\\internal_logs\\internallog.txt&quot;&gt;\n    &lt;targets&gt;\n        &lt;target name=&quot;logfile&quot; xsi:type=&quot;File&quot; \n                fileName=&quot;d:\\Projects\\CompanyEmployees\/Project\\logs\\${shortdate}_logfile.txt&quot; \n                layout=&quot;${longdate} ${level:uppercase=true} ${message}&quot;\/&gt;\n    &lt;\/targets&gt;\n    &lt;rules&gt;\n        &lt;logger name=&quot;*&quot; minlevel=&quot;Debug&quot; writeTo=&quot;logfile&quot; \/&gt;\n    &lt;\/rules&gt;\n&lt;\/nlog&gt;\n<\/pre>\n<\/p>\n<h2>2.4 Configuring Logger Service for Logging Messages<\/h2>\n<p>Setting up the configuration for a logger service is quite easy. First, we need to update the constructor of the <strong>Startup<\/strong> class:<br \/>\n\u8bbe\u7f6e\u8bb0\u5f55\u5668\u670d\u52a1\u7684\u914d\u7f6e\u975e\u5e38\u7b80\u5355\u3002\u9996\u5148\uff0c\u6211\u4eec\u9700\u8981\u66f4\u65b0 <strong>Startup<\/strong> \u7c7b\u7684\u6784\u9020\u51fd\u6570 \uff1a<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic Startup(IConfiguration configuration)\n        {\n            LogManager.LoadConfiguration(string.Concat(Directory.GetCurrentDirectory(), &quot;\/nlog.config&quot;)); \n            Configuration = configuration;\n        }\n<\/pre>\n<p>Basically, we are using NLog\u2019s <strong>LogManager<\/strong> static class with the LoadConfiguration method to provide a path to the configuration file.<br \/>\n\u57fa\u672c\u4e0a\uff0c\u6211\u4eec\u4f7f\u7528NLog\u7684<strong>LogManager<\/strong>\u9759\u6001\u7c7b\u548c<br \/>\n<strong>LoadConfiguration<\/strong> \u65b9\u6cd5\uff0c\u7528\u4e8e\u63d0\u4f9b\u914d\u7f6e\u6587\u4ef6\u7684\u8def\u5f84\u3002<\/p>\n<p>The next thing we need to do is to add the logger service inside the .NET Core\u2019s IOC container. There are three ways to do that:<br \/>\n\u6211\u4eec\u9700\u8981\u505a\u7684\u4e0b\u4e00\u4ef6\u4e8b\u662f\u5728 .NET Core \u7684 IOC \u5bb9\u5668\u4e2d\u6dfb\u52a0\u8bb0\u5f55\u5668\u670d\u52a1\u3002\u6709\u4e09\u79cd\u65b9\u6cd5\u53ef\u4ee5\u505a\u5230\u8fd9\u4e00\u70b9\uff1a<\/p>\n<ul>\n<li>By calling the  <strong>services.AddSingleton<\/strong> method, we can create a service the first time we request it and then every subsequent request will call the same instance of the service. This means that all components share the same service every time they need it and the same instance will be used for every method call.<br \/>\n\u901a\u8fc7\u8c03\u7528<strong>services.AddSingleton<\/strong>\u65b9\u6cd5\uff0c\u6211\u4eec\u53ef\u4ee5\u5728\u7b2c\u4e00\u6b21\u8bf7\u6c42\u5b83\u65f6\u521b\u5efa\u4e00\u4e2a\u670d\u52a1\uff0c\u7136\u540e\u6bcf\u4e2a\u540e\u7eed\u8bf7\u6c42\u5c06\u8c03\u7528\u8be5\u670d\u52a1\u7684\u540c\u4e00\u5b9e\u4f8b\u3002\u8fd9\u610f\u5473\u7740\u6240\u6709\u7ec4\u4ef6\u5728\u6bcf\u6b21\u9700\u8981\u65f6\u5171\u4eab\u76f8\u540c\u7684\u670d\u52a1\uff0c\u5e76\u4e14\u6bcf\u6b21\u65b9\u6cd5\u8c03\u7528\u90fd\u5c06\u4f7f\u7528\u76f8\u540c\u7684\u5b9e\u4f8b\u3002<\/li>\n<li>By calling the <strong>services.AddScoped<\/strong> method, we can create a service once per request. That means whenever we send an HTTP request to the application, a new instance of the service will be created.<br \/>\n\u901a\u8fc7\u8c03\u7528 <strong>services.AddScoped<\/strong> \u65b9\u6cd5\uff0c\u6211\u4eec\u53ef\u4ee5\u521b\u5efa\u6bcf\u4e2a\u8bf7\u6c42\u4e00\u6b21\u670d\u52a1\u3002\u8fd9\u610f\u5473\u7740\u6bcf\u5f53\u6211\u4eec\u5411\u5e94\u7528\u7a0b\u5e8f\u53d1\u9001HTTP\u8bf7\u6c42\u65f6\uff0c\u90fd\u4f1a\u521b\u5efa\u670d\u52a1\u7684\u65b0\u5b9e\u4f8b\u3002<\/li>\n<li>By calling the <strong>services.AddTransient<\/strong> method, we can create a service each time the application requests it. This means that if multiple components need the service, it will be created again for every single component request.<br \/>\n\u901a\u8fc7\u8c03\u7528<strong>services.AddTransient<\/strong>\u65b9\u6cd5\uff0c\u6211\u4eec\u53ef\u4ee5\u521b\u5efa\u4e00\u4e2a\u6bcf\u6b21\u5e94\u7528\u7a0b\u5e8f\u8bf7\u6c42\u65f6\u63d0\u4f9b\u670d\u52a1\u3002\u8fd9\u610f\u5473\u7740\uff0c\u5982\u679c\u591a\u4e2a\u7ec4\u4ef6\u9700\u8981\u8be5\u670d\u52a1\uff0c\u5219\u4f1a\u4e3a\u6bcf\u4e2a\u7ec4\u4ef6\u8bf7\u6c42\u518d\u6b21\u521b\u5efa\u8be5\u670d\u52a1\u3002<\/li>\n<\/ul>\n<p>So, let\u2019s add a new method in the<strong> ServiceExtensions<\/strong> class:<br \/>\n\u56e0\u6b64\uff0c\u8ba9\u6211\u4eec\u5728 <strong>ServiceExtensions<\/strong> \u7c7b\u4e2d\u6dfb\u52a0\u4e00\u4e2a\u65b0\u65b9\u6cd5\uff1a<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic static void ConfigureLoggerService(this IServiceCollection services) =&gt; \n            services.AddScoped&lt;ILoggerManager, LoggerManager&gt;();\n<\/pre>\n<p>And after that, we need to modify the ConfigureServices method to include our newly created extension method:<br \/>\n\u4e4b\u540e\uff0c\u6211\u4eec\u9700\u8981\u4fee\u6539 ConfigureServices \u65b9\u6cd5\u4ee5\u5305\u542b\u6211\u4eec\u65b0\u521b\u5efa\u7684\u6269\u5c55\u65b9\u6cd5\uff1a<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\npublic void ConfigureServices(IServiceCollection services)\n        {\n            services.ConfigureCors();\n            services.ConfigureIISIntegration();\n            services.ConfigureLoggerService();\n\n            services.AddControllers();\n        }\n<\/pre>\n<p>Every time we want to use a logger service, all we need to do is to inject it into the constructor of the class that needs it. .NET Core will resolve that service and the logging features will be available.<br \/>\n\u6bcf\u6b21\u6211\u4eec\u60f3\u8981\u4f7f\u7528\u8bb0\u5f55\u5668\u670d\u52a1\u65f6\uff0c\u6211\u4eec\u9700\u8981\u505a\u7684\u5c31\u662f\u5c06\u5176\u6ce8\u5165\u5230\u9700\u8981\u5b83\u7684\u7c7b\u7684\u6784\u9020\u51fd\u6570\u4e2d\u3002.NET Core \u5c06\u89e3\u6790\u8be5\u670d\u52a1\uff0c\u5e76\u4e14\u65e5\u5fd7\u8bb0\u5f55\u529f\u80fd\u5c06\u53ef\u7528\u3002<\/p>\n<p>This type of injecting a class is called Dependency Injection and it is built into .NET Core.<br \/>\n\u8fd9\u79cd\u7c7b\u578b\u7684\u6ce8\u5165\u7c7b\u79f0\u4e3a\u4f9d\u8d56\u5173\u7cfb\u6ce8\u5165\uff0c\u5b83\u5185\u7f6e\u4e8e .NET Core \u4e2d\u3002<\/p>\n<p>Let\u2019s learn a bit more about it.<br \/>\n\u8ba9\u6211\u4eec\u8fdb\u4e00\u6b65\u4e86\u89e3\u5b83\u3002<\/p>\n<h2>2.5 Di,Ioc,and Logger Service Testing<\/h2>\n<p>What is Dependency Injection (DI) exactly and what is IoC (Inversion of Control)?<br \/>\n\u7a76\u7adf\u4ec0\u4e48\u662f\u4f9d\u8d56\u6ce8\u5165\uff08DI\uff09\uff0c\u4ec0\u4e48\u662fIoC\uff08\u63a7\u5236\u53cd\u8f6c\uff09\uff1f\u200c<\/p>\n<p>Dependency injection is a technique we use to achieve the decoupling of objects and their dependencies. It means that rather than instantiating an object explicitly in a class every time we need it, we can instantiate it once and then send it to the class.<br \/>\n\u4f9d\u8d56\u6ce8\u5165\u662f\u6211\u4eec\u7528\u6765\u5b9e\u73b0\u5bf9\u8c61\u53ca\u5176\u4f9d\u8d56\u5173\u7cfb\u89e3\u8026\u7684\u4e00\u79cd\u6280\u672f\u3002\u8fd9\u610f\u5473\u7740\uff0c\u4e0e\u5176\u5728\u6bcf\u6b21\u9700\u8981\u65f6\u5728\u7c7b\u4e2d\u663e\u5f0f\u5b9e\u4f8b\u5316\u5bf9\u8c61\uff0c\u4e0d\u5982\u5c06\u5176\u5b9e\u4f8b\u5316\u4e00\u6b21\uff0c\u7136\u540e\u5c06\u5176\u53d1\u9001\u5230\u7c7b\u3002<\/p>\n<p>This is often done through a constructor. The specific approach we utilize is also known as the <strong>Constructor Injection<\/strong>.<br \/>\n\u8fd9\u901a\u5e38\u662f\u901a\u8fc7\u6784\u9020\u51fd\u6570\u5b8c\u6210\u7684\u3002\u6211\u4eec\u4f7f\u7528\u7684\u7279\u5b9a\u65b9\u6cd5\u4e5f\u79f0\u4e3a\u6784\u9020\u51fd\u6570\u6ce8\u5165(Constructor Injection)\u3002<\/p>\n<p>In a system that is designed around DI, you may find many classes requesting their dependencies via their constructors. In this case, it is helpful to have a class that manages and provides dependencies to classes through the constructor.<br \/>\n\u5728\u56f4\u7ed5 DI \u8bbe\u8ba1\u7684\u7cfb\u7edf\u4e2d\uff0c\u60a8\u53ef\u80fd\u4f1a\u53d1\u73b0\u8bb8\u591a\u7c7b\u901a\u8fc7\u5176\u6784\u9020\u51fd\u6570\u8bf7\u6c42\u5176\u4f9d\u8d56\u9879\u3002\u5728\u8fd9\u79cd\u60c5\u51b5\u4e0b\uff0c\u6709\u4e00\u4e2a\u7c7b\u901a\u8fc7\u6784\u9020\u51fd\u6570\u7ba1\u7406\u548c\u63d0\u4f9b\u7c7b\u7684\u4f9d\u8d56\u9879\u4f1a\u5f88\u6709\u5e2e\u52a9\u3002<\/p>\n<p>These classes are referred to as containers or more specifically, Inversion of Control containers. An IoC container is essentially a factory that is responsible for providing instances of the types that are requested from it.<br \/>\n\u8fd9\u4e9b\u7c7b\u79f0\u4e3a\u5bb9\u5668\uff0c\u6216\u8005\u66f4\u5177\u4f53\u5730\u8bf4\uff0c\u79f0\u4e3a\u63a7\u5236\u53cd\u8f6c\u5bb9\u5668\u3002IoC \u5bb9\u5668\u672c\u8d28\u4e0a\u662f\u4e00\u4e2a\u5de5\u5382\uff0c\u8d1f\u8d23\u63d0\u4f9b\u4ece\u4e2d\u8bf7\u6c42\u7684\u7c7b\u578b\u5b9e\u4f8b\u3002<\/p>\n<p>To test our logger service, we are going to use the default <strong>WeatherForecastController<\/strong>. You can find it in the main project in the Controllers folder. It comes with the ASP.NET Core Web API template.<br \/>\n\u4e3a\u4e86\u6d4b\u8bd5\u6211\u4eec\u7684\u8bb0\u5f55\u5668\u670d\u52a1\uff0c\u6211\u4eec\u5c06\u4f7f\u7528\u9ed8\u8ba4\u7684<strong>WeatherForecastController<\/strong>\u3002\u60a8\u53ef\u4ee5\u5728\u4e3b\u9879\u76ee\u7684\u201c\u63a7\u5236\u5668\u201d\u6587\u4ef6\u5939\u4e2d\u627e\u5230\u5b83\u3002\u5b83\u9644\u5e26\u4e86 ASP.NET \u6838\u5fc3 Web API \u6a21\u677f\u3002<\/p>\n<p>In the Solution Explorer, we are going to open the Controllers folder and locate the <strong>WeatherForecastController<\/strong> class. Let\u2019s modify it:<br \/>\n\u5728\u89e3\u51b3\u65b9\u6848\u8d44\u6e90\u7ba1\u7406\u5668\u4e2d\uff0c\u6211\u4eec\u5c06\u6253\u5f00\u63a7\u5236\u5668\u6587\u4ef6\u5939\u5e76\u627e\u5230 <strong>WeatherForecastController<\/strong> \u7c7b\u3002\u8ba9\u6211\u4eec\u4fee\u6539\u5b83\uff1a<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n\/\/ WeatherForecastController.cs\nusing Contracts;\nusing Microsoft.AspNetCore.Mvc;\nusing System;\nusing System.Collections.Generic;\n\nnamespace CompanyEmployees\n{\n    \/\/public class WeatherForecast\n    \/\/{\n    \/\/    public DateTime Date { get; set; }\n    \/\/    public int TemperatureC { get; set; }\n    \/\/    public int TemperatureF =&gt; 32 + (int)(TemperatureC \/ 0.5556);\n    \/\/    public string Summary { get; set; }\n    \/\/}\n\n    &#x5B;Route(&quot;&#x5B;controller]&quot;)]\n    &#x5B;ApiController]\n    public class WeatherForecastController : ControllerBase\n    {\n        private ILoggerManager _logger;\n        public WeatherForecastController(ILoggerManager logger) { _logger = logger; }\n        &#x5B;HttpGet]\n        public IEnumerable&lt;string&gt; Get()\n        {\n            _logger.LogInfo(&quot;Here is info message from our values controller.&quot;); \n            _logger.LogDebug(&quot;Here is debug message from our values controller.&quot;);\n            _logger.LogWarn(&quot;Here is warn message from our values controller.&quot;);\n            _logger.LogError(&quot;Here is an error message from our values controller.&quot;); \n            return new string&#x5B;] { &quot;value1&quot;, &quot;value2&quot; };\n        }\n    }\n\n}\n<\/pre>\n<p>Now let\u2019s start the application and browse to<br \/>\n\u73b0\u5728\uff0c\u8ba9\u6211\u4eec\u542f\u52a8\u5e94\u7528\u7a0b\u5e8f\u5e76\u6d4f\u89c8\u5230<br \/>\n<a href=\"https:\/\/localhost:5001\/weatherforecast\"><a href=\"https:\/\/localhost:5001\/weatherforecast\"><a href=\"https:\/\/localhost:5001\/weatherforecast\">https:\/\/localhost:5001\/weatherforecast<\/a><\/a><\/a>\u3002<\/p>\n<p>Tip: If you are using Windows 8 and having trouble starting this application on <a href=\"https:\/\/localhost:5001\"><a href=\"https:\/\/localhost:5001\"><a href=\"https:\/\/localhost:5001\">https:\/\/localhost:5001<\/a><\/a><\/a>..., you have to add a parameter to the appsetings.Development.json file:<br \/>\n\u63d0\u793a\uff1a \u5982\u679c\u60a8\u4f7f\u7528\u7684\u662fWindows 8\uff0c\u5e76\u4e14\u5728 <a href=\"https:\/\/localhost:5001\"><a href=\"https:\/\/localhost:5001\"><a href=\"https:\/\/localhost:5001\">https:\/\/localhost:5001<\/a><\/a><\/a> \u4e0a\u542f\u52a8\u6b64\u5e94\u7528\u7a0b\u5e8f\u65f6\u9047\u5230\u95ee\u9898...\uff0c\u5219\u5fc5\u987b\u5411\u5e94\u7528\u7a0b\u5e8f\u96c6\u6dfb\u52a0\u4e00\u4e2a\u53c2\u6570\u3002Development.json file\uff1a<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\n&quot;Kestrel&quot;: { \n    &quot;EndpointDefaults&quot;: { \n        &quot;Protocols&quot;: &quot;Http1&quot; \n    } \n}\n<\/pre>\n<p>As a result, you will see an array of two strings. Now go to the folder that you have specified in the <strong>nlog.config<\/strong> file, and check out the result. You should see two folders: the <strong>internal_logs<\/strong> folder and the <strong>logs<\/strong> folder. Inside the <strong>logs<\/strong> folder, you should find a file with the following logs:<br \/>\n\u7ed3\u679c\uff0c\u60a8\u5c06\u770b\u5230\u4e00\u4e2a\u7531\u4e24\u4e2a\u5b57\u7b26\u4e32\u7ec4\u6210\u7684\u6570\u7ec4\u3002\u73b0\u5728\u8f6c\u5230\u60a8\u5728<strong>nlog.config<\/strong> \u6587\u4ef6\u4e2d\u6307\u5b9a\u7684\u6587\u4ef6\u5939\uff0c\u7136\u540e\u67e5\u770b\u7ed3\u679c\u3002\u60a8\u5e94\u8be5\u4f1a\u770b\u5230\u4e24\u4e2a\u6587\u4ef6\u5939\uff1a<strong>internal_logs<\/strong> \u6587\u4ef6\u5939\u548c <strong>logs<\/strong>  \u6587\u4ef6\u5939\u3002\u5728 logs \u6587\u4ef6\u5939\u4e2d\uff0c\u60a8\u5e94\u8be5\u627e\u5230\u4e00\u4e2a\u5305\u542b\u4ee5\u4e0blogs\u7684\u6587\u4ef6\uff1a<\/p>\n<p><img decoding=\"async\" src=\"\/img\/20220824-ultimate-asp-net-core-web-api\/Image_2003.jpg\" alt=\"alt\" \/><\/p>\n<p>That\u2019s all we need to do to configure our logger for now. We\u2019ll add some messages to our code along with the new features.<br \/>\n\u8fd9\u5c31\u662f\u6211\u4eec\u73b0\u5728\u914d\u7f6e\u8bb0\u5f55\u5668\u6240\u9700\u8981\u505a\u7684\u3002\u6211\u4eec\u5c06\u5728\u4ee3\u7801\u4e2d\u6dfb\u52a0\u4e00\u4e9b\u6d88\u606f\u4ee5\u53ca\u65b0\u529f\u80fd\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>2 Configuring a Logging Service Why does logging messages matter so much during application development? While our application is in the development stage, it&#8217;s easy to debug the code and find out what happened. But debugging in a production environment is not that easy. \u4e3a\u4ec0\u4e48\u5728\u5e94\u7528\u7a0b\u5e8f\u5f00\u53d1\u8fc7\u7a0b\u4e2d\u8bb0\u5f55\u6d88\u606f\u5982\u6b64\u91cd\u8981\uff1f\u867d\u7136\u6211\u4eec\u7684\u5e94\u7528\u7a0b\u5e8f\u5904\u4e8e\u5f00\u53d1\u9636\u6bb5\uff0c\u4f46\u5f88\u5bb9\u6613\u8c03\u8bd5\u4ee3\u7801\u5e76\u627e\u51fa\u53d1\u751f\u4e86\u4ec0\u4e48\u3002\u4f46\u662f\u5728\u751f\u4ea7\u73af\u5883\u4e2d\u8fdb\u884c\u8c03\u8bd5\u5e76\u4e0d\u5bb9\u6613\u3002\u200c\u200c That&#8217;s why log messages are a great way to find [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[3],"tags":[23],"class_list":["post-138","post","type-post","status-publish","format-standard","hentry","category-csharp","tag-ultimate-asp-net-core-web-api"],"_links":{"self":[{"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/posts\/138","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=138"}],"version-history":[{"count":0,"href":"https:\/\/diji.net\/index.php?rest_route=\/wp\/v2\/posts\/138\/revisions"}],"wp:attachment":[{"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=138"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=138"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/diji.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=138"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}