You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

类库采用Event Aggregator替代日志:传递日志信息的实践问询

Handling Informational Logs in Class Libraries

Great question—you’re spot-on that logging shouldn’t be a core responsibility of a class library. The goal is to keep your library focused on its intended functionality, while letting consuming applications take ownership of cross-cutting concerns like logging. Let’s break down your options, including the Event Aggregator approach you’re considering.

Is an Event Aggregator a Best Practice?

Absolutely—this is a strong implementation of the publish-subscribe pattern, which fits perfectly here. Your library would emit events for meaningful informational moments (like "connection successful"), and consuming apps can subscribe to those events to log them (or take other actions, like updating a UI). This keeps your library completely decoupled from any specific logging framework, which is ideal for reusability across different projects.

Here’s a quick C# example to illustrate how this might work:

// Inside your class library
public class ConnectionService
{
    // Define an event for connection success events
    public event EventHandler<ConnectionStatusEventArgs>? ConnectionSucceeded;

    public void Connect()
    {
        // Execute your connection logic here...
        
        // Raise the event once the connection is successful
        OnConnectionSucceeded(new ConnectionStatusEventArgs("Successfully connected to server: XYZ-01"));
    }

    protected virtual void OnConnectionSucceeded(ConnectionStatusEventArgs e)
    {
        ConnectionSucceeded?.Invoke(this, e);
    }
}

// Custom event args to carry details about the event
public class ConnectionStatusEventArgs : EventArgs
{
    public string StatusMessage { get; }

    public ConnectionStatusEventArgs(string message)
    {
        StatusMessage = message;
    }
}

Then in the consuming application:

var connectionService = new ConnectionService();
// Subscribe to the event and log the message using the app's preferred logger
connectionService.ConnectionSucceeded += (sender, e) => 
    _appLogger.LogInformation(e.StatusMessage);

This approach shines if you expect multiple components in the consuming app to react to the same event (not just logging—think metrics tracking or user notifications).

Other Feasible Approaches

If an Event Aggregator feels like overkill for your use case, here are a few simpler alternatives to consider:

1. Inject a Platform-Agnostic Logging Abstraction

Many ecosystems (like .NET) provide generic logging abstractions (e.g., ILogger). Your library can accept this abstraction via constructor injection, allowing it to emit log messages without knowing the underlying logging implementation. The consuming app then provides the concrete logger (like Serilog, NLog, or the built-in Microsoft logger).

Example:

// Inside your class library
public class ConnectionService
{
    private readonly ILogger<ConnectionService> _logger;

    public ConnectionService(ILogger<ConnectionService> logger)
    {
        _logger = logger;
    }

    public void Connect()
    {
        // Execute connection logic...
        
        _logger.LogInformation("Successfully connected to server: XYZ-01");
    }
}

This is a great choice if you want your library to "suggest" log messages while leaving the actual logging behavior entirely up to the consumer. It’s lightweight and integrates seamlessly with most app ecosystems.

2. Callback Delegates

For straightforward scenarios, you can expose a callback delegate that the consuming app can set. Your library invokes this delegate with informational messages, and the app decides how to handle them (log, ignore, display to the user, etc.).

Example:

// Inside your class library
public class ConnectionService
{
    // Allow consumers to set a callback for informational messages
    public Action<string>? OnInformationalMessage { get; set; }

    public void Connect()
    {
        // Execute connection logic...
        
        OnInformationalMessage?.Invoke("Successfully connected to server: XYZ-01");
    }
}

Consuming app usage:

var connectionService = new ConnectionService
{
    OnInformationalMessage = msg => _appLogger.LogInformation(msg)
};

This is the simplest approach, but it’s limited to a single callback (unlike events, which support multiple subscribers).

3. Custom Logger Interface

If you want full control over the logging contract without tying to a platform-specific abstraction, define your own logger interface in the library. Consuming apps implement this interface using their preferred logging framework and pass it to your library.

Example:

// Inside your class library
public interface ILibraryLogger
{
    void LogInfo(string message);
    void LogWarning(string message);
    // Add other log levels as needed
}

public class ConnectionService
{
    private readonly ILibraryLogger _logger;

    public ConnectionService(ILibraryLogger logger)
    {
        _logger = logger;
    }

    public void Connect()
    {
        // Execute connection logic...
        
        _logger.LogInfo("Successfully connected to server: XYZ-01");
    }
}

This approach gives you complete control over what logging methods your library exposes, while still keeping it decoupled from any specific logging implementation.

Which Approach Should You Pick?

  • Event Aggregator: Best if you need multiple components in the consuming app to react to events (e.g., logging + UI updates + metrics tracking).
  • Logging Abstraction: Ideal if you want to align with standard platform practices and let consumers use their existing logging setup.
  • Callback Delegates: Perfect for simple, single-purpose scenarios where you only need one handler for informational messages.
  • Custom Logger Interface: Great if you need a tailored logging contract that’s independent of platform-specific tools.

All of these approaches follow the key principle of keeping logging responsibility out of your class library, so they’re all valid depending on your project’s needs.

内容的提问来源于stack exchange,提问作者Josh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:24:24