为什么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()
}
}
答案 0 :(得分:2)
将AddOrder
和ExecuteOrder
更改为内部,并在同一个程序集中有两个代理类,每个代理类都可以使用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
您应该注意,客户仍然可以通过反射调用这些方法,甚至是私有方法。