Архитектура C # 3 уровня - PullRequest
1 голос
/ 26 ноября 2010

Я создал решение для выигрышной формы в C #.Решение имеет три проекта: бизнес-уровень переднего уровня (FL) и уровень данных (DL).

Передний уровень имеет все формы.Все формы реализуют интерфейс IForms. Бизнес-уровень имеет всю бизнес-логику.Все классы бизнес-логики реализуют интерфейс IController. Уровень данных имеет всю логику данных, которая взаимодействует с базой данных sql.Все классы логики данных наследуют интерфейс IModel

Я пытаюсь использовать шаблон проектирования MVC, но немного борюсь.
Цель: вызвать метод в классе BL, когда я нажимаю кнопку вформа.

Если я добавлю BL dll в FL, то я могу вызвать методы BL.

BL.Class classObject = new BL.Class(this);
classObject.CallMethod();

В BL я хочу иметь ссылку на объект, который вызвалметод, поэтому я попытался добавить ссылку на FL DLL, но он говорит, что круговая ссылка DLL.

Я хочу иметь конструктор в классе BL:

public BL.Class (представление IView){MessageBox (view.Name);}

Как мне разработать решение для достижения этой цели?Обратите внимание, что решение большое, поэтому я не могу объединить все классы в одну DLL.

Берегите себя, FM

Ответы [ 7 ]

4 голосов
/ 26 ноября 2010

Вы пытаетесь внедрить логику представления в свой бизнес-уровень. Ваш BL не должен создавать окна сообщений - это ответственность уровня презентации.

2 голосов
/ 26 ноября 2010

Основная идея многоуровневой архитектуры заключается в том, что n-й уровень должен взаимодействовать с n + 1-м уровнем, но никогда не пересекать промежуточный уровень, поэтому n-й уровень не может прыгать и напрямую взаимодействовать с n + 2-м уровнем.

это был принцип архитектуры, теперь перейдем к вашему делу.

1- Во-первых, вы говорите о 3-уровневой архитектуре, это не 3-уровневая архитектура, потому что вы не размещаете свой DAL ИЛИ BL на отдельном сервере, но вы создаете отдельные слои в своем решении (путем создания отдельного проекта)

2- Так как у вас есть три DLLS (FL, BL, DAL), теперь ваше наслоение должно быть FL -> BL ----> DAL, где ---> обозначает, с кем разговаривали.

Как вы достигнете выше пути (FL -> BL ----> DAL) в вашем приложении?

Для этого вы можете добавить ссылку на DAL в проекте BL и ссылку BL на ваш проект FL, чтобы вы могли придерживаться архитектурного принципа, изложенного выше.

Как реализовать MVC в вашем случае?

1- 'C' обозначает Controller в MVC, Controller - это класс, который отвечает за обновление FL и вашей модели. Поэтому вам необходимо создать отдельный уникальный контроллер для отдельных уникальных функций в вашем приложении (обратите внимание, вам не нужно создавать контроллер для каждой формы в приложении), поэтому если у вас есть модуль заказа, чем создать OrderBaseController и передать этот контроллер как ссылка на ваши взгляды (Winform)

2- Контроллер, созданный на шаге 1, может предоставлять модель (помните, у нас есть ссылка BL в нашем FL), которая может использоваться OrderView.

3 - Представление может изменить модель через контроллер (примечание, что модель в BL, но у нас есть ссылка в нашем FL), но фактические изменения базы данных все еще не зафиксированы.

Как вы будете выполнять шаг 3 выше?

    interface IOrderController
{
    bool SaveOrder(order order);
    bool ValidateOrder(order order);
    order GetOrder();
}

public class OrderBaseController : IOrderController
{
    private OrderServiceFacade Orderhelper { get; set; }

    public OrderBaseController()
    {
        Orderhelper = new OrderServiceFacade();
    }

    public bool ValidateOrder(order objOrder)
    {
    }

    #region IOrderController Members

    public bool SaveOrder(order order)
    {
        bool success = false;
        if (ValidateOrder(order))
        {
           success = Orderhelper.SaveOrder(order);

        }

        return success;
    }

    #endregion

    #region IOrderController Members


    public order GetOrder()
    {
        throw new NotImplementedException();
    }

    #endregion
}

мы только что внедрили ordercontroller. Теперь пришло время присоединить этот контроллер к представлению.

 public partial class Form1 : Form
{
    IOrderController Controller;

    public order OrderToBeSaved { get; set; }
    public Form1()
    {
        InitializeComponent();
        Controller = new OrderBaseController(); // you have the controller , 
        // controller creation can also be delegated to some other component but that's totally different issue.

        OrderToBeSaved = Controller.GetOrder(); // You got the order object here , once you get the order object you can bind its properties to the different control.



    }
}

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

теперь пришло время сохранить заказ

 private void btnSave_Click(object sender, EventArgs e)
    {
        Controller.SaveOrder(OrderToBeSaved);
    }

здесь мы удалили логику сохранения в контроллер, теперь давайте посмотрим, как сохранить данные из контроллера. Для Контроллера сохраните заказ, он должен пройти через цепочку, то есть он должен иметь некоторую логику для разговора с BL (Контроллер находится в FL)

Поскольку у нас есть ссылка на BL в нашем FL, мы можем напрямую общаться с BL, но мы проходим еще одну концепцию проектирования, которую мы называем ServiceFacade, класс ServiceFacade, который будет использоваться для делегирования задачи от одного уровня к другому. слой. * * одна тысяча сорок-два

 class OrderServiceFacade
{
    public bool SaveOrder(order order)
    {
       return  OrderDAO.SaveOrder(order);
    }
}

Наконец, нам нужно сохранить заказ в базе данных, поэтому нам нужно определить класс в нашем DAL, мы называем его OrderDAO.

static class OrderDAO
{
    static public  bool SaveOrder(order order)
     {
            // put logic to access database and save the data.
     }

    static DataTable GetOrder(int OrderID);
}

он не завершен, но дает представление о том, как MVC работает в многоуровневом сценарии.

2 голосов
/ 26 ноября 2010

Вы можете определить события в BL для регистрации FL. Всякий раз, когда происходит изменение в модели, BL должен инициировать событие. Это для представления, чтобы справиться с этим.

Ваш BL создан в окне сообщения. Что если ваш взгляд - это WebForm? BL не должен знать детали зрения.

Кроме того, ваш проект BL не должен иметь dll-ссылку на FL. Вам нужно объявить IView в BL, а не FL.

EDIT: Это структура, которую я использовал раньше. Ваш BL определяет интерфейс. Ваш взгляд должен реализовать интерфейс, если он хочет использовать BL. BL использует интерфейс для взаимодействия с представлением. Таким образом, вы можете создавать различные представления, которые используют один и тот же BL.

BL.dll

public interface IView
{
    /// <summary>Update the view</summary>
    void UpdateView(object myBusinessObject);

    /// <summary>Display message</summary>
    void ShowMessage(string msg);
}

public class BL
{
    // Model and View
    private IView _view;

    /// <summary>Constructor</summary>
    public BL (IView view)
    {
        _view = view;
    }

    public void foo()
    {
        // Do something

        // Show message
        _view.ShowMessage("Hello World");
    }
}

FL.dll

public class FL
{
    private BL _myBL;

    /// <summary>Constructor</summary>
    public FL ()
    {
        _myBL = new BL(this);
    }

    /// <summary>Handles user event</summary>
    public void handleEvent()
    {
        // Call BL to do something

        _myBL.foo();
    }

    public void UpdateView(object myBusinessObject)
    {
        // Update your view
    }

    public void ShowMessage(string msg)
    {
        // Display message to user
    }
}
2 голосов
/ 26 ноября 2010

Я знаю, что ваши формы программирования выигрывают, но вы можете взглянуть на шаблоны WebFormsMVP или MVVM, чтобы получить некоторые идеи.

"В BL я хочу иметь ссылку на объект, который вызвал метод, поэтому я попытался добавить ссылку на FL dll, но там говорится, что ссылка Circular dll."

В частности, в проекте WebFormsMVP аргументы передаются между слоями в зависимости от того, как они находятся в среде .Net, например (отправитель объекта, mySpecialEventArgs e) - второй аргумент в параметре «mySpecialEventArgs» содержит всю передаваемую информацию туда и сюда.

1 голос
/ 26 ноября 2010

Есть на самом деле предлагаемые проекты для этого типа вещей.Большая часть документации по этому вопросу специально направлена ​​на WPF, которую вы найдете, если посмотрите на MVVM (другое название MVC).

По сути, вам понадобится четвертая библиотека, которая является своего рода каркасным уровнем.Вот что вам нужно:

класс ServiceProvider - то, что реализует IServiceProvider.

Зачем нам это нужно?Потому что ваш FL собирается предоставлять услуги пользовательского интерфейса.В вашем случае служба MessageBox.Тем не менее, вы можете обнаружить, что это настолько полезно, что вы захотите создать другие сервисы.Как что-то, чтобы найти файл или папку.Это еще не все, но сейчас мы будем придерживаться этого.

Ваш класс ServiceProvider должен также хранить список служб, о которых он знает, и предоставлять способ добавления в этот список.Полный поставщик услуг, вероятно, будет включать следующее.

private readonly Dictionary<Type,object> mServices = new Dictionary<Type,object>();
public void Add(Type type,object value)  { ...}
public object GetService(Type serviceType) { ... }
public void Remove(Type type)  { ... }
public T Resolve<T>()  { return (T)this.GetService(typeof(T)); } 

Если вы сделаете его одноэлементным классом, вы сможете использовать этот сервис в любом месте.

Следующее задание - создание сервисов.В вашей новой среде dll создайте интерфейс, такой как IMessageBoxService, с набором методов, которые вы можете вызывать, чтобы вызвать сообщение для пользователя.Вы можете начать с простой функции, подобной следующей, и добавить ее при необходимости позже.

void ShowError(string message);

Затем вам нужно будет реализовать этот интерфейс в вашей FL dll.Эта реализация будет выполнять фактические вызовы MessageBox.

Следующим шагом будет регистрация вашей новой реализации службы у поставщика услуг.Так что где-то перед открытием GUI вызовите ServiceProvider.add(typeof(IMessageBoxService), new MyMessageBoxService());

Теперь в вашей бизнес-логике каждый раз, когда вам нужно всплывающее сообщение, вы можете спросить поставщика услуг об услуге окна сообщения и вызвать нужный метод вIMessageBoxService.Примерно так ...

IMessageBoxService wMess = ServiceProvider.GetInstance().Resolve<IMessageBoxService>();
wMess.ShowError("My Error Message");

Теперь у вас есть чистый и красивый MVC-совместимый дизайн для всплывающих сообщений об ошибках без каких-либо неприятных циклических зависимостей.

Если вы хотите узнать больше о MVVMи что это все о вы можете проверить ссылку Microsoft.Или есть полная структура MVVM, которую кто-то взял на себя труд для создания WPF, которая имеет много интересных функций.Если у вас есть время, вы можете посмотреть на это.

Microsoft представляет MVVM

MVVM Framework

0 голосов
/ 26 ноября 2010

Почему БЛ должен знать о ФЛ?Настоящий BL не зависит от FL. В настоящий момент FL реализуется с использованием WindowsForms, если позднее необходимо было изменить FL на WPF, то BL также необходимо изменить.Тогда что было слоем, если изменение одного слоя влияет и на другой слой?Идея BL заключается в том, что он не зависит от уровня представления, но может использоваться разными FL.BL не должен делать никаких предположений или должен знать о FL.

0 голосов
/ 26 ноября 2010

Вы не сможете знать оба слоя друг о друге, если они реализованы как отдельные проекты (вызывает циклические зависимости).

Один из способов сделать это - использовать шаблон наблюдателя. Настройте события в бизнес-классах и сделайте подписной слой подписанным на эти события. Когда бизнес-уровень завершает свои действия, он может инициировать события и передавать результаты обратно в представление. Бизнес-классу не нужно знать о уровне представления, он просто знает, что на него подписаны объекты, и избегает создания циклических зависимостей.

Обновление: вот один из способов заставить BL вызывать FL, используя события. Это своего рода круговая логика, но если вы уже структурировали свой код вокруг двух уровней, зная друг о друге, то вы можете рассмотреть это.

class BL
{
    public void CallFromFL (int parameter)
    {
        int result = DoSomeWork (parameter);
        if (OnComplete != null)
            OnComplete (result);
    }
    public event Action <int> OnComplete;
}

class FL
{
    void Foo ()
    {
        BL bl = new BL ();
        bl.OnComplete += this.getResult;
        bl.CallFromFL (5);
    }

    void GetResult (int result) {...}
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...