Files
XplorePlane/XP.Common/Documents/Logging.EXAMPLES.md
T

7.7 KiB
Raw Blame History

日志服务使用示例 | Logger Service Usage Examples

示例 1:服务类中使用 | Example 1: Usage in Service Class

旧方式(手动传递字符串)| Old Way (Manual String)

public class PlcService
{
    private readonly ILoggerService _logger;

    public PlcService(ILoggerService logger)
    {
        // 需要手动输入类名,容易出错
        // Need to manually type class name, error-prone
        _logger = logger?.ForModule("PlcService") ?? throw new ArgumentNullException(nameof(logger));
    }
}

// 日志输出 | Log output:
// [PlcService] 正在初始化 PLC 连接...

新方式(自动类型推断)| New Way (Auto Type Inference)

public class PlcService
{
    private readonly ILoggerService _logger;

    public PlcService(ILoggerService logger)
    {
        // 自动获取完整类型名,重构安全
        // Automatically get full type name, refactoring-safe
        _logger = logger?.ForModule<PlcService>() ?? throw new ArgumentNullException(nameof(logger));
    }
}

// 日志输出 | Log output:
// [XP.Hardware.Plc.Services.PlcService] 正在初始化 PLC 连接...

示例 2ViewModel 中使用 | Example 2: Usage in ViewModel

using Prism.Mvvm;
using XP.Common.Logging.Interfaces;

namespace XP.Hardware.RaySource.ViewModels
{
    public class RaySourceOperateViewModel : BindableBase
    {
        private readonly ILoggerService _logger;

        public RaySourceOperateViewModel(ILoggerService logger)
        {
            // 自动使用:XP.Hardware.RaySource.ViewModels.RaySourceOperateViewModel
            // Automatically uses: XP.Hardware.RaySource.ViewModels.RaySourceOperateViewModel
            _logger = logger?.ForModule<RaySourceOperateViewModel>() ?? throw new ArgumentNullException(nameof(logger));
            
            _logger.Info("射线源操作视图模型已初始化 | Ray source operate view model initialized");
        }

        public void StartXRay()
        {
            _logger.Info("用户请求启动射线 | User requested to start X-ray");
            // ... 业务逻辑 | business logic
        }
    }
}

示例 3:工厂类中使用 | Example 3: Usage in Factory Class

using XP.Common.Logging.Interfaces;
using XP.Hardware.RaySource.Abstractions;

namespace XP.Hardware.RaySource.Factories
{
    public class RaySourceFactory : IRaySourceFactory
    {
        private readonly ILoggerService _logger;

        public RaySourceFactory(ILoggerService logger)
        {
            // 自动使用:XP.Hardware.RaySource.Factories.RaySourceFactory
            // Automatically uses: XP.Hardware.RaySource.Factories.RaySourceFactory
            _logger = logger?.ForModule<RaySourceFactory>() ?? throw new ArgumentNullException(nameof(logger));
        }

        public IXRaySource CreateRaySource(string deviceType)
        {
            _logger.Info("创建射线源实例:类型={DeviceType} | Creating ray source instance: type={DeviceType}", deviceType);
            
            switch (deviceType)
            {
                case "Comet225":
                    return new Comet225RaySource(_logger);
                default:
                    _logger.Error(null, "不支持的设备类型:{DeviceType} | Unsupported device type: {DeviceType}", deviceType);
                    throw new NotSupportedException($"不支持的设备类型:{deviceType}");
            }
        }
    }
}

示例 4:静态方法中使用 | Example 4: Usage in Static Methods

public class ConfigLoader
{
    public static PlcConfig LoadConfig(ILoggerService logger)
    {
        // 静态方法中也可以使用泛型
        // Can also use generics in static methods
        var log = logger.ForModule<ConfigLoader>();
        
        log.Info("正在加载 PLC 配置 | Loading PLC configuration");
        
        try
        {
            // ... 加载逻辑 | loading logic
            log.Info("PLC 配置加载成功 | PLC configuration loaded successfully");
            return config;
        }
        catch (Exception ex)
        {
            log.Error(ex, "PLC 配置加载失败 | PLC configuration loading failed");
            throw;
        }
    }
}

示例 5:嵌套类中使用 | Example 5: Usage in Nested Classes

public class RaySourceService
{
    private readonly ILoggerService _logger;

    public RaySourceService(ILoggerService logger)
    {
        _logger = logger?.ForModule<RaySourceService>() ?? throw new ArgumentNullException(nameof(logger));
    }

    // 嵌套类 | Nested class
    public class ConnectionManager
    {
        private readonly ILoggerService _logger;

        public ConnectionManager(ILoggerService logger)
        {
            // 自动使用:XP.Hardware.RaySource.Services.RaySourceService+ConnectionManager
            // Automatically uses: XP.Hardware.RaySource.Services.RaySourceService+ConnectionManager
            _logger = logger?.ForModule<ConnectionManager>() ?? throw new ArgumentNullException(nameof(logger));
        }
    }
}

示例 6:混合使用 | Example 6: Mixed Usage

有时你可能想要自定义模块名以保持简洁:

public class VeryLongNamespaceAndClassName
{
    private readonly ILoggerService _logger;

    public VeryLongNamespaceAndClassName(ILoggerService logger)
    {
        // 选项 1:使用完整类型名(详细但冗长)
        // Option 1: Use full type name (detailed but verbose)
        // _logger = logger?.ForModule<VeryLongNamespaceAndClassName>();
        // 输出 | Output: [XP.Some.Very.Long.Namespace.VeryLongNamespaceAndClassName]

        // 选项 2:使用简短自定义名(简洁但需手动维护)
        // Option 2: Use short custom name (concise but needs manual maintenance)
        _logger = logger?.ForModule("VeryLong") ?? throw new ArgumentNullException(nameof(logger));
        // 输出 | Output: [VeryLong]
    }
}

优势对比 | Advantages Comparison

ForModule() 的优势 | Advantages of ForModule()

重构安全:重命名类时自动更新
Refactoring-safe: Automatically updates when renaming class

无拼写错误:编译器检查类型
No typos: Compiler checks type

完整信息:包含命名空间,便于定位
Complete info: Includes namespace, easy to locate

智能提示IDE 自动补全
IntelliSense: IDE auto-completion

ForModule(string) 的优势 | Advantages of ForModule(string)

简洁输出:日志文件更易读
Concise output: Log files more readable

自定义名称:可以使用业务术语
Custom names: Can use business terms

灵活性:可以为不同场景使用不同名称
Flexibility: Can use different names for different scenarios

场景 推荐方式 原因
服务类 ForModule<T>() 需要完整追踪
ViewModel ForModule<T>() 需要完整追踪
工厂类 ForModule<T>() 需要完整追踪
简单工具类 ForModule("ToolName") 保持简洁
临时调试 ForModule("Debug") 快速定位
第三方集成 ForModule("ThirdParty.XXX") 明确标识
Scenario Recommended Reason
Service classes ForModule<T>() Need full tracing
ViewModels ForModule<T>() Need full tracing
Factory classes ForModule<T>() Need full tracing
Simple utility classes ForModule("ToolName") Keep concise
Temporary debugging ForModule("Debug") Quick location
Third-party integration ForModule("ThirdParty.XXX") Clear identification