13

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

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

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

4

4 回答 4

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 中的某个类。

那有意义吗?

于 2012-12-27T01:59:20.183 回答
10

我建议你使用事件和监听器。例如,您可以从 ProjectB 发送消息,Trace.WriteLine而在 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*/
};
于 2012-12-27T01:15:01.670 回答
1

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

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

于 2012-12-27T01:15:20.547 回答
0

我实际上会在 ClassB 上创建自己的活动

public event EventHandler MySpecialHook;

EventHandler 是一个标准的委托

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

然后,在您的 Class A 中,在创建 ClassB 的实例之后,当 B 中发生 A 应该知道的事情时,挂钩到事件处理程序以进行通知。很像 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.
   }
}
于 2012-12-27T01:35:55.507 回答