添加引用时的循环依赖(委托)

时间:2014-04-22 02:23:11

标签: c# circular-dependency

基本上我有2个项目,一个表单和一个用户控件。

我需要它们都在不同的项目中,但是表单需要引用用户控件,因为它使用的是用户控件。并且用户控件将需要使用表单类之一来引用表单。当我添加第二个因为它需要时,VS会抱怨循环依赖,这是可以理解的。我该如何解决这个问题?

4 个答案:

答案 0 :(得分:2)

逻辑上,表单应取决于用户控件。您可以创建一个接口来替换用户控件项目中的表单,然后让表单实现该接口。

示例用户控制项目;

public interface IForm
{
    string MyString { get; }
}

public class MyUserControl : UserControl
{
     public IForm Form { get; set; }

     private void ShowMyString()
     {
          String myString = Form.MyString;
          ...
     }
}

示例表单项目

public class MyForm : Form, IForm
{
    public MYString { get "My String Value"; }
}

答案 1 :(得分:2)

我认为问题的根本原因是您没有正确区分表单和控件之间的问题。

由于你有一个(有点通用的)控件,它不应该依赖于表单。控件的所有逻辑都应该驻留在控件本身内。表单应该只使用黑盒子来控制:添加它,设置公共字段,调用公共方法等等。其他任何东西都违反了封装。

有时,控件可能需要了解其父表单的内容。在这种情况下,我建议一些简单的事情,如向子控件添加Parent字段。

如果您需要表单中更具体的内容,您可以随时添加界面;界面应该只列出控件从表单中需要的东西。例如,如果您需要大小,可以添加:

public interface IControlParent {
  int Width { get; }
  int Height { get; }
}

通过这种方式,您可以清楚地看到依赖项(控件需要父项的内容),如果父类型/合同发生更改,则您不需要执行更改控制类的操作。

答案 2 :(得分:0)

你必须对你的代码进行分离,对于应用程序集的引用绝不是一个好主意,如果你将来尝试重用它,应用程序exe应该与控件一起使用。

因此,从表单项目中获取类并将其移动到控件项目或创建库项目,将类放在其上并从控件和应用程序项目中引用它。

答案 3 :(得分:0)

您应该使用事件(委托)。我们假设您在表单项目中创建了一个类:Form1。在用户控件内部,您定义了UserControl1。 UserControl1需要实例化并从Form1调用方法:

public class Form1
{
    public void Execute(string sMessage)
    {
        Console.WriteLine(sMessage);
        Console.ReadLine();
    }
}

的UserControl1:

public class UserControl
{
    public Func<object, object> oDel = null;

    public void Execute()
    {
        oDel?.Invoke("HELLO WORLD!");
    }
}

从实例化UserControl的类中,我们称之为ParentClass:

public class ParentClass
{
    public void Execute()
    {
        UserControl oUserControl = new UserControl();
        oUserControl.oDel = Form1Action;
        oUserControl.Execute();
    }

    public object Form1Action(object obj)
    {
        string sObj = Convert.ToString(obj);

        Form1 oForm = new Form1();
        oForm.Execute(sObj);

        return null;
    }
}

这种方法负责将事件处理到高级别课程。