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

C#中如何获取类声明的泛型类型以验证委托签名实现信号系统

C#类型安全信号系统的实现优化

我要在C#中实现一套编译阶段即可完成信号与委托验证的类型安全信号系统,设定了三个优先级需求:

  • 类型安全:开发者不得向预定义信号的监听器传递错误参数类型,也不能注册签名不匹配的函数。
  • 语法简洁:创建新信号、注册/注销监听器、触发信号的操作需快捷简便,无冗余代码负担。
  • 参数描述性:触发信号时,参数名称需体现其在该信号中的具体用途,例如使用(string userName, int userAge)而非(string param1, int param2)。

目前前两项需求已实现,但第三项尚未达成,同时我对现有实现的语法冗余问题也不满意。


当前实现方案

信号基类(需按泛型参数数量重复实现,如SigClass<T,U>、SigClass<T,U,V>等)

public delegate void Callback<T>(T arg1);

public class SigClass<T>
{
    protected static Dictionary<string, Delegate> _event = new Dictionary<string, Delegate>();
    
    public static void Send<C>(T p1) where C : SCSigBase
    {
        string s = typeof(C).Name;
        if (!_event.ContainsKey(s)) { _event.Add(s, null);}
        Callback<T> callback = _event[s] as Callback<T>;
        callback?.Invoke(p1);
    }
    
    public static void Register<C>(Callback<T> function) where C : SCSigBase
    {
        string s = typeof(C).Name;
        if (!_event.ContainsKey(s)) { _event.Add(s, null);}
        
        _event[s] = (Callback<T>)_event[s] + function;
    }
    
    public static void Unregister<C>(Callback<T> function) where C : SCSigBase
    {
        string s = typeof(C).Name;
        if (!_event.ContainsKey(s)) { _event.Add(s, null);}
        
        _event[s] = (Callback<T>)_event[s] - function;
    }
}

声明新信号类型

public class FooSig : SigClass<string> {}

注册/注销监听器、触发信号

public void RunTests()
{     
    FooSig.Register<FooSig>(Bar);
    FooSig.Send<FooSig>("Hello, world!");
    FooSig.Unregister<FooSig>(Bar);
    FooSig.Send<FooSig>("You should not see this.");
}

public void Bar(string message) 
{
    Console.Write(message);
}

此处的泛型参数<C>仅用于避免相同泛型参数的信号冲突,属于冗余代码,我希望将其优化掉。


优化尝试与核心问题

我想将调用逻辑简化为以下形式:不再通过继承类(如FooSig)持有方法和静态字典,而是使用一个静态类SignalManager,通过传入信号类型完成验证:

public void RunTests()
{
    SignalManager.Register<FooSig>(Bar);
    SignalManager.Send<FooSig>("Hello, world!");
    SignalManager.Unregister<FooSig>(Bar);
    SignalManager.Send<FooSig>("You should not see this.");
}

现在的核心问题是:
是否存在方法可以获取类声明时使用的泛型类型,并利用该类型验证传递的委托签名?

换句话说,当我声明FooSig : SigClass<string>{}时,能否在验证委托签名时复用这个string泛型类型?


期望实现的编译期验证效果

我希望代码能达到以下编译阶段的校验效果:

public class FooSig : SigClass<string>{}

public void RunTests()
{
    SignalManager.Register<FooSig>(Bar);
    SignalManager.Register<FooSig>(Baz); // 此代码应编译失败,Baz的签名与FooSig的泛型类型不匹配

    SignalManager.Send<FooSig>("Hello, world!");
    SignalManager.Send<FooSig>(); // 此代码应编译失败,FooSig要求传入string类型参数
}

public void Bar(string param)
{
    // 执行操作
}

public void Baz(int param)
{
    // 执行操作
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 19:39:54