Циклическая зависимость при добавлении ссылки (Делегаты)

В основном у меня есть 2 проекта, форма и пользовательский элемент управления.

Мне нужно, чтобы они оба находились в разных проектах, но форма должна ссылаться на пользовательский элемент управления, поскольку он использует пользовательский элемент управления. И пользовательский элемент управления должен будет ссылаться на форму, поскольку он использует один из классов формы. Когда я добавлю второй, потому что ему нужен , VS будет жаловаться на круговую зависимость, что понятно. Как мне это решить?


person user3398315    schedule 22.04.2014    source источник
comment
Можете ли вы абстрагировать классы, не относящиеся к пользовательскому интерфейсу, из проекта Forms и создать DLL?   -  person shree.pat18    schedule 22.04.2014
comment
Создайте третий проект, содержащий все, как необходимое для формы и пользовательского элемента управления. Без этого вы никогда не заставите свои сборки работать правильно.   -  person Peter Ritchie    schedule 22.04.2014


Ответы (4)


Логически форма должна зависеть от пользовательского элемента управления. Вы можете создать интерфейс для замены формы в проекте пользовательского элемента управления, а затем сделать так, чтобы форма реализовывала этот интерфейс.

Пример проекта пользовательского контроля;

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"; }
}
person Adrian Toman    schedule 22.04.2014

Я думаю, что основная причина вашей проблемы заключается в том, что вы не разделили свои проблемы между формой и элементом управления должным образом.

Поскольку у вас есть (несколько общий) элемент управления, он не должен зависеть от формы. Вся логика элемента управления должна находиться внутри самого элемента управления. Форма должна потреблять элемент управления только черным ящиком: добавлять его, устанавливать публичные поля, вызывать публичные методы и т. д. Все остальное является нарушением инкапсуляции.

Иногда элементам управления может потребоваться информация о своей родительской форме. В этом случае я бы предложил что-то столь же простое, как добавление поля Parent в дочерний элемент управления.

если от формы нужно что-то более конкретное, всегда можно добавить интерфейс; интерфейс должен перечислять только те вещи, которые нужны элементу управления из формы. Например, если вам нужен размер, вы можете добавить:

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

Таким образом, вы ясно видите зависимости (что элементу управления нужно от родителя), и если родительский тип/контракт изменяется, вам не нужно делать столько, чтобы изменить свой класс элемента управления.

person ashes999    schedule 22.04.2014

Вы должны отделить свой код, никогда не рекомендуется иметь ссылку на сборку приложения, если вы попытаетесь повторно использовать его в будущем, исполняемый файл приложения должен идти с элементом управления.

Итак, возьмите класс из проекта формы и переместите его в проект управления или создайте проект библиотеки, поместите в него класс и ссылайтесь на него из своего элемента управления и проектов приложений.

person Gusman    schedule 22.04.2014

Вы должны использовать событие (делегата). Предположим, что внутри вашего проекта формы вы создали один класс: 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;
    }
}

Этот подход возлагает ответственность за обработку события на класс высокого уровня.

person Andrés    schedule 04.04.2017