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

如何在C#中实现编译期强制的类型关联,无需额外泛型参数?

实现编译期可强制的类型间关联方案

我明白你想要的是一种能让编译器帮你强制校验的类型关联方案——不需要额外传入类型参数,仅仅通过第一组的类型(比如Nail)就能直接拿到对应第二组的实例(比如NailMaker)。下面是一个能满足你需求的实现思路,完全不需要在调用时指定额外的类型参数:

1. 定义抽象基类 Maker<T>

这个基类负责维护类型关联的静态存储,以及对外提供获取实例的入口:

public abstract class Maker<T>
{
    // 静态字段存储对应类型的Maker实例
    private static Maker<T>? _registeredMaker;

    // 受保护的注册方法,仅允许派生类调用
    protected static void Register(Maker<T> makerInstance)
    {
        if (_registeredMaker != null)
            throw new InvalidOperationException($"A Maker for type {typeof(T)} is already registered.");
        
        _registeredMaker = makerInstance;
    }

    // 对外公开的静态获取方法,无需额外类型参数
    public static Maker<T> Get()
    {
        return _registeredMaker 
            ?? throw new InvalidOperationException($"No Maker registered for type {typeof(T)}. Ensure the corresponding Maker class is included in your project.");
    }

    // 可添加抽象业务方法,让具体Maker类实现
    public abstract void CreateProduct();
}

2. 实现具体的Maker类

针对每个第一组类型(比如Nail),实现对应的Maker类,并通过静态构造函数完成自动注册:

// 第一组类型:Nail(无需任何与Maker相关的代码)
public class Nail { }

// 对应的第二组类型:NailMaker
public class NailMaker : Maker<Nail>
{
    // 静态构造函数会在第一次访问NailMaker类型时自动执行,完成注册
    static NailMaker()
    {
        Register(new NailMaker());
    }

    public override void CreateProduct()
    {
        Console.WriteLine("Created a Nail!");
    }
}

// 同理实现Screw和ScrewMaker
public class Screw { }

public class ScrewMaker : Maker<Screw>
{
    static ScrewMaker()
    {
        Register(new ScrewMaker());
    }

    public override void CreateProduct()
    {
        Console.WriteLine("Created a Screw!");
    }
}

3. 调用方式

现在你可以完全按照期望的方式调用,不需要传入任何额外类型参数:

// 获取Nail对应的Maker实例,类型为NailMaker
var nailFactory = Maker<Nail>.Get();
nailFactory.CreateProduct(); // 输出:Created a Nail!

// 获取Screw对应的Maker实例,类型为ScrewMaker
var screwFactory = Maker<Screw>.Get();
screwFactory.CreateProduct(); // 输出:Created a Screw!

4. 实现编译期强制校验

如果想要确保每个第一组类型都有对应的Maker类(达到编译器强制的效果),可以借助Roslyn分析器:

  • 编写一个自定义分析器,扫描项目中所有第一组类型(比如可以用特性标记这些类型)
  • 检查每个标记的类型是否存在对应的Maker<T>派生类,并且完成了注册
  • 如果缺失,在编译阶段抛出警告或错误,实现真正的编译期强制约束

这个方案的核心是利用了C#静态构造函数的特性——当第一次访问具体Maker类型时,自动完成注册,后续调用Maker<T>.Get()就能直接拿到对应实例,完全不需要额外传入类型参数,完美契合你的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 10:15:29