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

C#与VB类库循环引用下跨库方法触发实现咨询

解决类库A(VB)与类库B(C#)的跨库事件触发问题(避免循环引用)

需求可行性

完全可行。核心思路是解耦依赖关系,保持A引用B、B不引用A的单向依赖,通过事件/回调机制让A主动注册到B的实例上,既避免循环引用,又能实现触发逻辑。

原方案失败原因

你之前的代码中,A类内部new了一个独立的ClassB实例,但定时任务执行的是另一个完全不同的ClassB实例——两个实例的事件体系相互独立,因此定时任务执行SomeMethod时,A类注册的事件不会被触发。

解决方案

以下是几种实用的实现方式,均无需修改单向依赖关系:

方法1:全局单例实例注册事件

让定时任务使用的ClassB实例成为全局可访问的单例,A类获取该实例并注册事件。

C#类库B修改代码:

public delegate void MethodExecutedEventHandler();

public class ClassB
{
    // 静态属性,持有定时任务使用的实例
    public static ClassB Instance { get; private set; }

    public event MethodExecutedEventHandler MethodExecuted;

    public ClassB()
    {
        // 初始化时将当前实例赋值给静态属性(确保定时任务通过new创建实例时执行此逻辑)
        Instance = this;
    }

    public void SomeMethod()
    {
        // 原有业务逻辑
        // 触发事件
        MethodExecuted?.Invoke();
    }
}

VB类库A修改代码:

Public Class ClassA
    Private WithEvents b As ClassB

    Public Sub New()
        ' 获取定时任务使用的全局ClassB实例
        b = ClassB.Instance
    End Sub

    Private Sub OnMethodExecuted() Handles b.MethodExecuted
        ' 这里写你需要执行的逻辑
    End Sub
End Class

注意:需保证定时任务初始化ClassB的时机早于A类实例化,否则Instance会为null。

方法2:依赖注入(DI)管理实例

通过DI容器将ClassB注册为单例,注入到A类中,确保两者使用同一个实例。

C#类库B保持原有事件定义:

public delegate void MethodExecutedEventHandler();

public class ClassB
{
    public event MethodExecutedEventHandler MethodExecuted;

    public void SomeMethod()
    {
        // 原有业务逻辑
        MethodExecuted?.Invoke();
    }
}

VB类库A修改代码(通过构造函数注入):

Public Class ClassA
    Private WithEvents b As ClassB

    ' 构造函数注入ClassB实例
    Public Sub New(bInstance As ClassB)
        b = bInstance
    End Sub

    Private Sub OnMethodExecuted() Handles b.MethodExecuted
        ' 这里写你需要执行的逻辑
    End Sub
End Class

启动项目(如控制台/Web项目)配置DI:

var services = new ServiceCollection();
// 注册ClassB为单例
services.AddSingleton<ClassB>();
// 注册ClassA,DI容器会自动注入ClassB实例
services.AddSingleton<ClassA>();
var serviceProvider = services.BuildServiceProvider();

// 定时任务从容器中获取ClassB实例执行SomeMethod
var classBInstance = serviceProvider.GetRequiredService<ClassB>();
// 定时任务逻辑:每分钟调用classBInstance.SomeMethod()

方法3:回调函数注册

如果不想用事件,也可以让B类提供回调注册方法,A类将自己的方法传递给B实例。

C#类库B修改代码:

public class ClassB
{
    private Action _executedCallback;

    // 提供注册回调的方法
    public void RegisterMethodExecutedCallback(Action callback)
    {
        _executedCallback = callback;
    }

    public void SomeMethod()
    {
        // 原有业务逻辑
        // 触发回调
        _executedCallback?.Invoke();
    }
}

VB类库A修改代码:

Public Class ClassA
    Public Sub New(bInstance As ClassB)
        ' 注册回调方法
        bInstance.RegisterMethodExecutedCallback(AddressOf OnMethodExecuted)
    End Sub

    Private Sub OnMethodExecuted()
        ' 这里写你需要执行的逻辑
    End Sub
End Class

总结

所有方案的核心都是确保A类注册事件/回调的ClassB实例,与定时任务执行SomeMethod的实例是同一个,同时保持A引用B的单向依赖,彻底避免循环引用问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 14:07:52