C#中两个项目的循环依赖

我在名为ProjectA(ConsoleApplication)和ProjectB(ClassLibrary)的解决方案中有两个项目。 ProjectA引用了ProjectB。 一般来说,ProjectA调用ProjectB中的方法来执行一些操作并将结果返回给ProjectA。 但有时,我需要ProjectB向ProjectA发送一些“附加”信息(更具体地说,是调用ProjectA中的Console.WriteLine()方法)。 为了实现这一点,我需要在ProjectB中引用ProjectA,但是当我尝试这样做时,我收到以下错误:

A reference to ProjectA could not be added. Adding this project as a reference would cause a circular dependency A reference to ProjectA could not be added. Adding this project as a reference would cause a circular dependency

我理解整个耦合概念,并且获取此消息确实有意义,但是,在某些情况下,我需要向ProjectA发送其他信息。 有任何想法吗?

我建议你使用事件和听众。 例如,您可以通过Trace.WriteLine从ProjectB发送消息,而在ProjectA中,您可以为跟踪添加订户。 .NET已经提供了一个ConsoleTraceListener类,用于将Trace消息路由到Console。 您可以通过以下方式从ProjectA添加侦听器:

 Trace.Listeners.Add(new ConsoleTraceListener()); 

或者,如果您不想使用集成类,可以在ProjectB中构建一个非常简单的“源”类,它将使用Action作为其签名公开事件(尽管我建议您创建一个委托对于它),然后从ProjectA订阅它。 通常,.NET类更灵活。

项目B

 public static class MyTrace { public static event Action MessageReceived; internal static void Broadcast(string message) { if (MessageReceived != null) MessageReceived(message); } } 

项目A

 MyTrace.MessageReceived += s => { /*Operate*/ }; 

实际上可以创建具有可成功编译的循环依赖项的项目,但我强烈建议不要这样做。 相反,组织您的项目,以便他们有一个非循环依赖图。

有许多方法可以解决这个问题,其中一些已经在其他答案中提到过。 尚未发布的是完全消除项目A和项目B之间的依赖关系,并创建第三个项目C,它定义A和B通信的接口。 那是:

 namespace C { public interface IFoo { void Frob(); } public interface IBar { void Qux(); } } 

然后使项目A和B引用项目C,并使其类实现IFoo,IBar等。 当项目A中的方法需要在项目B中的对象上调用Frob时,它通过获取IFoo而不是在B中获取某个类来实现。

那有意义吗?

你不能这样做。 如果项目互相调用,它们应该在同一个项目中。 或者,ProjectB可以将其信息公开,而不是ProjectB调用ProjectA,因此ProjectA可以访问它。

你不能拥有循环依赖。 你怎么能? 编译器如何知道首先构建哪个? 您有一个基本的设计问题,那就是需要修复的问题。

我实际上会在ClassB上创建自己的事件

 public event EventHandler MySpecialHook; 

EventHandler是一个标准的委托

 public delegate void EventHandler(object sender, EventArgs e); 

然后,在A类中,在创建ClassB实例之后,挂钩到事件处理程序,以便在A应该知道的B中发生某些事情时进行通知。 很像OnActivated,OnLostFocus,OnMouseMove或类似的事件(但他们有委托不同的签名)

 public class ClassB { public event EventHandler MySpecialHook; public void SomeMethodDoingActionInB() { // do whatever you need to. // THEN, if anyone is listening (via the class A sample below) // broadcast to anyone listening that this thing was done and // they can then grab / do whatever with results or any other // properties from this class as needed. if( MySpecialHook != null ) MySpecialHook( this, null ); } } public class YourClassA { ClassB YourObjectToB; public YourClassA { // create your class YourObjectToB = new ClassB(); // tell Class B to call your "NotificationFromClassB" method // when such event requires it YourObjectToB += NotificationFromClassB; } public void NotificationFromClassB( object sender, EventArgs e ) { // Your ClassB did something that your "A" class needs to work on / with. // the "sender" object parameter IS your ClassB that broadcast the notification. } }