C# C中两个项目中的循环依赖#
我在一个名为ProjectA(ConsoleApplication)和ProjectB(ClassLibrary)的解决方案中有两个项目。ProjectA引用了ProjectB。一般来说,ProjectA在ProjectB中调用一个方法来做一些事情并将结果返回给ProjectA。但是,有时我需要ProjectB向ProjectA发送一些“附加”信息(更具体地说是调用ProjectA中的C# C中两个项目中的循环依赖#,c#,circular-dependency,C#,Circular Dependency,我在一个名为ProjectA(ConsoleApplication)和ProjectB(ClassLibrary)的解决方案中有两个项目。ProjectA引用了ProjectB。一般来说,ProjectA在ProjectB中调用一个方法来做一些事情并将结果返回给ProjectA。但是,有时我需要ProjectB向ProjectA发送一些“附加”信息(更具体地说是调用ProjectA中的Console.WriteLine()方法)。为了实现这一点,我需要在ProjectB中引用ProjectA,但
Console.WriteLine()
方法)。为了实现这一点,我需要在ProjectB中引用ProjectA,但当我尝试这样做时,我得到以下错误:
无法添加对ProjectA的引用。将此项目添加为引用将导致循环依赖关系
我理解整个耦合概念,并且得到这个消息是有意义的,但是,在某些情况下,我需要向ProjectA发送额外的信息。有什么想法吗?我建议你使用事件和听众。例如,您可以通过
Trace.WriteLine
从ProjectB发送消息,而在ProjectA中,您可以为跟踪添加订户。NET已经提供了一个ConsoleTraceListener
类,用于将Trace
消息路由到控制台。您可以通过以下方式从ProjectA添加侦听器:
Trace.Listeners.Add(new ConsoleTraceListener());
或者,如果您不想使用集成类,您可以在ProjectB中构建一个非常简单的“源”类,该类将公开一个以Action
作为签名的事件(尽管我建议您为它创建一个委托),然后从ProjectA订阅它。通常,.NET类更灵活
项目b
public static class MyTrace
{
public static event Action<string> MessageReceived;
internal static void Broadcast(string message)
{
if (MessageReceived != null) MessageReceived(message);
}
}
你不能这样做。如果项目相互调用,则它们应位于同一项目中。或者,代替ProjectB调用ProjectA,ProjectB可以公开它的信息,这样ProjectA就可以访问它
不能有循环依赖项。你怎么能?编译器如何知道首先构建哪个?您有一个基本的设计问题,这就是需要解决的问题。我实际上会在ClassB上创建您自己的事件
public event EventHandler MySpecialHook;
EventHandler是的标准委托
public delegate void EventHandler(object sender, EventArgs e);
然后,在类A中,在创建了类B的实例之后,当B中发生了A应该知道的事情时,钩住事件处理程序进行通知。很像OnActivated、OnLostFocus、OnMouseMove或类似事件(但它们具有不同的委托签名)
实际上,创建具有循环依赖项的项目是可以成功编译的,但我强烈建议不要这样做。相反,组织项目,使其具有非循环依赖关系图 有很多方法可以解决这个问题,其中一些已经在其他答案中提到。一个尚未发布的是完全消除项目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中的某个类来实现
这有意义吗?我的两个类都是静态的。很好的方法,尽管你激起了我的好奇心——你如何创建具有循环依赖关系的项目,并成功编译?
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.
}
}
namespace C
{
public interface IFoo { void Frob(); }
public interface IBar { void Qux(); }
}