Классовая архитектура, друзья запрещены - PullRequest
0 голосов
/ 26 апреля 2010

Вопрос о том, почему в C # нет друзей, широко обсуждался.

У меня следующая проблема дизайна.

У меня есть два класса TradingSystem и Order . TradingSystem В классе есть только одна открытая функция AddOrder (Order ord). Клиенты могут вызывать только эту функцию . Вся остальная логика должна быть скрыта. Класс Order прослушивает рыночные события и должен вызывать другие функции TradingSystem ExecuteOrder, поэтому я также должен сделать ее публичной. Сделав это, я позволю клиентам торговой системы вызывать эту функцию, а я этого не хочу.

UPDATE Класс ордера и TradingSystem находятся в отдельных сборках. Класс заказа является базовым класс и многие другие классы могут быть получены.

    class TradingSystem
    {
     // Trading system stores list of orders
      List<Order> _orders;

     // this function is made public so that Order class can call it when need
     // but other class must not call it
      public ExecuteOrder(Order ord)
    {
 // some logic
    }  
      // this function is made public for external clients
      public AddOrder(OrderRequest ordreq)
     {
       // omitted code
       // create order and pass it this 
       order.OnOrderAdded(this);
     }
    }

    class Order
    {
      // reference to TradingSystem class is stored to call it methods
      TradingSystem _ts;

      public void OnOrderAdded(TradingSystem ts)
    {
       _ts = ts;
    }

   // this function is called on timer
    void OnMarketEvent()
    {
       if(/*some logic*/)
      _ts.ExecuteOrder()
    }  
    }

Ответы [ 5 ]

2 голосов
/ 26 апреля 2010

Ключевое слово C # internal является эквивалентом Friend VB. Объедините это с InternalsVisisibleToAttribute, и в этом примере вы должны быть в безопасности.

2 голосов
/ 26 апреля 2010

Вы можете создать два интерфейса для TradingSystem, один для клиентов и один для ордеров. Ваши клиенты получают ваш первый интерфейс, а Заказы - второй (вместо самой TradingSystem).

public interface I1
{
    void AddOrder(Order ord);
}

public interface I2
{
    void ExecuteOrder(Order ord);
}

internal class TradingSystem: I1, I2
{
    ...
2 голосов
/ 26 апреля 2010

Измените AddOrder и ExecuteOrder на внутренние, и у вас будет два прокси-класса в одной сборке, каждый из которых может быть создан с помощью TradingSystem и делегирует один из методов.

Затем вы даете все, что нужно для вызова AddOrder прокси, который может сделать это, и все, что нужно для вызова ExecuteOrder прокси, который может сделать это.

Вы могли бы потенциально оставить оба метода общедоступными и просто заставить TradingSystem реализовать два интерфейса - но это позволило бы клиентам просто привести к конкретному типу и в любом случае выполнить вызов.

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

1 голос
/ 26 апреля 2010

Если оба класса находятся в одной сборке, а клиенты - нет, вы можете использовать ключевое слово internal.

Внутреннее ключевое слово - доступ модификатор для типов и членов типов. Внутренние типы или члены доступны только внутри файлов в та же сборка.

Если это не так, вы все равно можете использовать ключевое слово internal, но вы должны объявить, что внутренние компоненты сборки, декларирующие TradingSystem, видны сборке, содержащей Order. Для этого вы можете использовать атрибут InternalsVisisibleTo.

Класс InternalsVisibleToAttribute

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

1 голос
/ 26 апреля 2010

Предполагая, что все клиенты находятся за пределами вашей сборки, вы можете объявить ExecuteOrder как internal.

В противном случае вы можете объявить интерфейс, который предоставляет один метод, и предоставить этот интерфейс клиентам вместо объекта. На самом деле, если API по своей сути является единичным, вы можете предоставить клиенту не более чем Action<OrderRequest>.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...