类架构,不允许朋友

时间:2010-04-26 09:40:24

标签: c# architecture oop

为什么C#中没有朋友的问题已被广泛讨论。

我有以下设计问题。

我有两个课程 TradingSystem 订单 TradingSystem 类只有一个公共函数AddOrder(Order ord)。 允许客户端仅调用此函数。必须隐藏所有其他逻辑。 订单类正在监听市场事件,必须调用TradingSystem ExecuteOrder的其他功能,因此我也必须公开它。这样做我将允许交易系统的客户调用此功能,我不希望这样。

更新 订单类和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 个答案:

答案 0 :(得分:2)

AddOrderExecuteOrder更改为内部,并在同一个程序集中有两个代理类,每个代理类都可以使用TradingSystem创建并委派其中一个方法。< / p>

然后你提供任何需要调用AddOrder代理的东西,它可以做到这一点,以及任何需要调用ExecuteOrder代理的东西。

您可以将两个方法都公开,只需让TradingSystem实现两个接口 - 但这样就可以让客户端转换为具体类型并进行调用。

顺便说一下,访问修饰符通常不应该用作安全层 - 如果这是一个真正的交易系统(而不仅仅是你想要的那种分离的例子)那么我会期望安全性实施方式不同。

答案 1 :(得分:2)

您可以为TradingSystem创建两个界面,一个用于客户端,一个用于订单。您的客户获得您的第一个界面,订单获得第二个(而不是TradingSystem本身)。

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

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

internal class TradingSystem: I1, I2
{
    ...

答案 2 :(得分:2)

C#关键字internal相当于VB的Friend。将此与InternalsVisisibleToAttribute相结合,在此示例中您应该安全回家。

答案 3 :(得分:1)

假设所有客户都在程序集之外,您可以将ExecuteOrder声明为internal

否则,您可以声明一个公开一个方法的接口,并将该接口提供给客户端而不是该对象。事实上,如果API本质上是单数,那么您可以为客户提供Action<OrderRequest>以外的任何内容。

答案 4 :(得分:1)

如果两个类都在同一个程序集中而客户端不在同一个程序集中,则可以使用internal关键字。

  

内部关键字是一种访问权限   类型和类型成员的修饰符。   内部类型或成员是   只能在文件中访问   同样的集会。

如果不是,您仍然可以使用internal关键字,但必须声明声明TradingSystem的程序集的内部对包含Order的程序集可见。为此,您可以使用属性InternalsVisisibleTo

InternalsVisibleToAttribute Class

您应该注意,客户仍然可以通过反射调用这些方法,甚至是私有方法。