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
相关产品推荐
相关产品推荐

