我在一个名为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
。
我理解整个耦合概念,并且获取此消息确实有意义,但是,在某些情况下,我需要向ProjectA发送其他信息。有什么想法吗?
答案 0 :(得分:15)
实际上可以创建具有循环依赖关系的项目,这些项目已成功编译,但我强烈建议不要使用它。相反,组织您的项目,使他们有一个非循环依赖图。
有许多方法可以解决这个问题,其他几个问题已在其他答案中提到过。尚未发布的是完全消除项目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中获取某个类来实现。
这有意义吗?
答案 1 :(得分:10)
我建议你使用事件和听众。例如,您可以通过Trace.WriteLine
从ProjectB发送消息,而在ProjectA中,您可以为跟踪添加订户。 .NET已经提供了ConsoleTraceListener
类,用于将Trace
消息路由到控制台。您可以通过以下方式从ProjectA添加侦听器:
Trace.Listeners.Add(new ConsoleTraceListener());
或者,如果您不想使用集成类,可以在ProjectB中构建一个非常简单的“源”类,它将以Action<string>
作为其签名公开事件(尽管我建议您为它创建一个委托),然后从ProjectA订阅它。通常,.NET类更灵活。
<强>项目B 强>
public static class MyTrace
{
public static event Action<string> MessageReceived;
internal static void Broadcast(string message)
{
if (MessageReceived != null) MessageReceived(message);
}
}
<强>项目A 强>
MyTrace.MessageReceived += s =>
{
/*Operate*/
};
答案 2 :(得分:1)
你不能这样做。如果项目互相调用,它们应该在同一个项目中。或者,ProjectB可以将其信息公开,而不是ProjectB调用ProjectA,因此ProjectA可以访问它。
您不能拥有循环依赖关系。你怎么能?编译器如何知道首先构建哪个?你有一个基本的设计问题,那就是需要解决的问题。
答案 3 :(得分:0)
我实际上会在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.
}
}