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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:15:37