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

本文关键字:循环 依赖 关系 引用 委托 添加 | 更新日期: 2023-09-27 17:59:20

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

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

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

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

用户控制项目示例;

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"; }
}

我认为问题的根本原因是您没有正确地将关注点在表单和控件之间分离。

既然你有一个(有点通用的)控件,它就不应该依赖于窗体。控件的所有逻辑都应该位于控件本身。表单应该只使用黑框:添加它、设置公共字段、调用公共方法等。其他任何操作都违反了封装。

有时,控件可能需要了解其父窗体的相关信息。在这种情况下,我建议做一些简单的事情,比如向子控件添加一个Parent字段。

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

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

通过这种方式,您可以清楚地看到依赖关系(控件需要从父级获得什么),并且如果父类型/约定发生了更改,则无需对控件类进行太多更改。

您必须对代码进行分隔,引用应用程序集从来都不是一个好主意,如果您将来试图重用它,应用程序exe应该与控件一起使用。

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

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

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

用户控制1:

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;
    }
}

这种方法将处理事件的责任交给高级类。