C# Framework4.6.1中依赖注入构建日志基础设施,工厂类初始化NLog.Logger
Alright, let's tackle this problem step by step. You're working in .NET Framework 4.6.1, want to build a logging infrastructure with dependency injection, use a factory to initialize NLog.Logger instances, and skip Unity's LoggerFactory.Resolve() method. Here's a solid, Unity-free approach:
Instead of relying on Unity's built-in resolution, we'll create our own lightweight logging abstraction, wrap NLog in it, build a factory to handle NLog instance creation, and integrate this with a flexible dependency injection container (we'll use Microsoft's DI package since it's compatible with Framework 4.6.1 and doesn't lock you into Unity).
First, create a simple ILogger interface to decouple your application from NLog directly. This makes it easy to switch loggers later if needed:
public interface ILogger { void Info(string message); void Error(string message, Exception exception = null); void Warn(string message); // Add other log levels as required (Debug, Trace, etc.) }
Next, build a concrete implementation of ILogger that uses NLog under the hood. This class will initialize the NLog.Logger instance directly:
public class NLogLogger : ILogger { private readonly global::NLog.Logger _nLogInstance; // Initialize NLog.Logger using the target type's full name (great for categorizing logs) public NLogLogger(Type loggerOwnerType) { _nLogInstance = global::NLog.LogManager.GetLogger(loggerOwnerType.FullName); } public void Info(string message) { _nLogInstance.Info(message); } public void Error(string message, Exception exception = null) { if (exception != null) _nLogInstance.Error(exception, message); else _nLogInstance.Error(message); } public void Warn(string message) { _nLogInstance.Warn(message); } }
Create a factory interface and implementation to handle creating ILogger instances. This factory is where we'll handle NLog initialization—no Unity resolve calls needed:
public interface ILoggerFactory { ILogger CreateLogger(Type loggerOwnerType); ILogger CreateLogger<T>(); // Convenience method for generic types } public class NLogLoggerFactory : ILoggerFactory { public ILogger CreateLogger(Type loggerOwnerType) { // Directly instantiate our NLog wrapper - no Unity Resolve() here! return new NLogLogger(loggerOwnerType); } public ILogger CreateLogger<T>() { return CreateLogger(typeof(T)); } }
We'll use Microsoft.Extensions.DependencyInjection (install via NuGet: Install-Package Microsoft.Extensions.DependencyInjection) to wire everything up. This is a lightweight, flexible DI container that works perfectly with Framework 4.6.1.
First, configure the container:
// Initialize the service collection var services = new ServiceCollection(); // Register our logger factory as a singleton (we only need one instance across the app) services.AddSingleton<ILoggerFactory, NLogLoggerFactory>(); // Example: Register a business service that needs logging public class OrderProcessingService { private readonly ILogger _logger; // Inject the factory, then create a logger for this specific service public OrderProcessingService(ILoggerFactory loggerFactory) { _logger = loggerFactory.CreateLogger<OrderProcessingService>(); } public void ProcessOrder(int orderId) { _logger.Info($"Starting processing for order #{orderId}"); try { // Your business logic here } catch (Exception ex) { _logger.Error($"Failed to process order #{orderId}", ex); } } } // Register your business service (transient, scoped, or singleton based on needs) services.AddTransient<OrderProcessingService>(); // Build the service provider var serviceProvider = services.BuildServiceProvider();
Don't forget to add an NLog.config file to your project (set its "Copy to Output Directory" property to "Copy if newer"):
<?xml version="1.0" encoding="utf-8" ?> <nlog xmlns="http://www.nlog-project.org/schemas/NLog.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" autoReload="true"> <targets> <!-- Log to console --> <target name="console" xsi:type="Console" layout="${longdate} | ${level:uppercase=true} | ${logger} | ${message}" /> <!-- Log to rolling file --> <target name="file" xsi:type="File" fileName="logs/app-${shortdate}.log" layout="${longdate} | ${level:uppercase=true} | ${logger} | ${message} ${exception:format=ToString}" /> </targets> <rules> <logger name="*" minlevel="Info" writeTo="console,file" /> </rules> </nlog>
- No Unity Dependency: We're not using Unity's
LoggerFactory.Resolve()at all—our factory directly creates NLog instances. - Decoupling: The
ILoggerabstraction keeps your business code separate from NLog, making testing and future logger swaps easier. - Clean DI Integration: The factory is registered as a singleton, so you get consistent logger creation across your app, and services receive the factory via constructor injection (following DI best practices).
Finally, resolve your service from the container and use it:
var orderService = serviceProvider.GetService<OrderProcessingService>(); orderService.ProcessOrder(123);
内容的提问来源于stack exchange,提问作者user3580768

