如何在C#中实现泛型类型在类间传递至泛型属性?
解决方案:将泛型类型从类传递到静态类的泛型属性
哎,我看了你的代码和需求,核心是想让静态类Log能直接拿到GenericLogger<T>里的泛型实例,实现类似Log.GenerciLog.Passed.Write(...)的简洁调用对吧?先帮你梳理下原代码里的几个编译级错误,这些是必须先解决的:
GenericLogger的Write方法是静态的,但它引用了实例字段_logManager——静态方法不能访问实例成员,得改成实例方法。- 静态类
Log里定义了实例字段_logManager和实例构造函数——静态类只能有静态成员,不能有实例成员,得把_logManager改成静态的。 Log的GenerciLog属性用了未定义的T——静态类本身不是泛型的,所以T没有上下文,编译器根本不知道这个T是什么。
接下来针对你的核心需求,给你两个可行的实现方案:
方案一:通过注册/获取机制实现(推荐)
这个方案不用修改太多原有结构,通过静态类Log作为统一入口,管理不同类型的日志容器实例:
调整Logger程序集代码
namespace Logger { public class GenericLogger<T> { private readonly LogManager _logManager; // 暴露泛型上下文(如果业务需要使用的话) public T LogContext { get; } public GenericLogger(string logName, T logContext = default) { _logManager = new LogManager(logName); LogContext = logContext; } // 改成实例方法,因为要访问实例专属的日志管理器 public void Write(string description) { _logManager.Write(description); } } public static class Log { // 静态类只能有静态成员,默认日志管理器改成静态 private static readonly LogManager _defaultLogManager = new LogManager(); // 用字典存储已注册的日志容器 private static readonly Dictionary<Type, object> _registeredContainers = new Dictionary<Type, object>(); // 注册日志容器的方法(程序启动时调用一次即可) public static void RegisterContainer<T>(T containerInstance) { if (!_registeredContainers.ContainsKey(typeof(T))) { _registeredContainers.Add(typeof(T), containerInstance); } } // 获取已注册的日志容器 public static T GetContainer<T>() { if (_registeredContainers.TryGetValue(typeof(T), out var container)) { return (T)container; } throw new InvalidOperationException($"未找到类型为{typeof(T)}的日志容器,请先注册。"); } // 全局默认日志写入方法 public static void Write(string description) { _defaultLogManager.Write(description); } } // 假设你的LogManager实现大概是这样(文件写入逻辑) public class LogManager { private readonly string _logFileName; public LogManager(string logFileName = "Log.txt") { _logFileName = logFileName; } public void Write(string description) { File.AppendAllText(_logFileName, $"{DateTime.Now:yyyy-MM-dd HH:mm:ss}: {description}{Environment.NewLine}"); } } }
调整Main程序集代码
using Logger; namespace DataProcessor { internal class SpecialLogger { // 用Lazy延迟初始化Passed日志实例,避免提前加载 private static readonly Lazy<GenericLogger<SpecialLogger>> _passed = new Lazy<GenericLogger<SpecialLogger>>(() => new GenericLogger<SpecialLogger>("Passed.txt"), true); public static GenericLogger<SpecialLogger> Passed => _passed.Value; // 同理初始化Failed日志实例 private static readonly Lazy<GenericLogger<SpecialLogger>> _failed = new Lazy<GenericLogger<SpecialLogger>>(() => new GenericLogger<SpecialLogger>("Failed.txt"), true); public static GenericLogger<SpecialLogger> Failed => _failed.Value; } internal class Processor { public void ProcessRate() { // 程序启动时注册一次即可,不用每次调用都重复注册 Log.RegisterContainer(SpecialLogger); var trans = dataManager.GetData(); // 假设dataManager是你的数据获取实例 Log.Write(trans.Count + " transaction found"); foreach (var item in trans) { try { // 事务处理逻辑... // 通过Log获取SpecialLogger容器,再调用Passed的Write方法 Log.GetContainer<SpecialLogger>().Passed.Write($"处理成功:{item}"); } catch (Exception ex) { Log.GetContainer<SpecialLogger>().Failed.Write($"处理失败:{item},错误信息:{ex.Message}"); } } } } }
方案二:将Log改成泛型静态类
如果你更偏好Log<SpecialLogger>.GenericLog.Passed.Write(...)这种语法,可以把Log改成泛型静态类,每个泛型参数会对应独立的静态实例:
调整Logger程序集的Log类
public static class Log<T> { // 泛型静态类的属性,每个T会有自己独立的实例 public static T GenericLog { get; internal set; } private static readonly LogManager _logManager = new LogManager(); public static void Write(string description) { _logManager.Write(description); } }
调整Main程序集的SpecialLogger
internal class SpecialLogger { // 静态构造函数里给泛型Log赋值,确保初始化一次 static SpecialLogger() { Log<SpecialLogger>.GenericLog = new SpecialLogger(); } // 保留原来的Passed和Failed属性(改成实例属性) private static readonly Lazy<GenericLogger<SpecialLogger>> _passed = new Lazy<GenericLogger<SpecialLogger>>(() => new GenericLogger<SpecialLogger>("Passed.txt"), true); public GenericLogger<SpecialLogger> Passed => _passed.Value; private static readonly Lazy<GenericLogger<SpecialLogger>> _failed = new Lazy<GenericLogger<SpecialLogger>>(() => new GenericLogger<SpecialLogger>("Failed.txt"), true); public GenericLogger<SpecialLogger> Failed => _failed.Value; }
调用方式
// 在Processor里这样调用 Log<SpecialLogger>.Write(trans.Count + " transaction found"); // ... Log<SpecialLogger>.GenericLog.Passed.Write($"处理成功:{item}");
这个方案的缺点是,每个泛型参数T会创建独立的Log<T>静态实例,如果你有很多不同的日志容器,需要注意内存占用情况。
内容的提问来源于stack exchange,提问作者Neeraj Kumar Gupta
相关产品推荐
相关产品推荐

