给定以下类:

public interface ISession {}

public class Session : ISession
{
    internal Uri ServerUri { get; private set; } // not in interface obviously
}


现在,我在同一项目中有另一个依赖于Session的类:

public  interface IDataClass {}

internal DataClass : IDataClass
{
    private readonly Session _session;

    public DataClass(ISession session)
    {
        _session = (Session) session;
    }

    // some more methods that access the internal property _session.ServerUri
    // and call methods on the session object
    // ...
}


因此,实际上Session类非常复杂。对于DataClass的单元测试,我将构造函数参数设置为ISession,因此我能够模拟依赖关系并验证ISession模拟中的某些方法调用。

但是,DataClass中的某些方法必须访问_session.ServerUri属性,因此该字段的类型必须为Session而不是ISession

我还可以使类型为ISession的字段,并在每次访问内部属性时强制转换该字段,这将使在此特定位置更加清楚为什么甚至需要具体的internal类。

每当我以上述方式实现强制转换时,我都会以某种方式想知道,如果采用更好的代码设计,是否可以避免强制转换。通常,我找到了一种更好的方法并摆脱了演员表。

但是上面的例子呢?这是好的代码设计吗?还是有更清洁的方法?我只是觉得以上述方式初始化构造函数的字段很奇怪。

最佳答案

您是正确的,因为这样的转换容易出错,因为编译器没有简单的方法来告诉它将要失败。

但是,问题的根源似乎在于缺乏对ServerUri属性的访问权限,因此您添加了强制转换作为解决方法。如果是这样,您应该可以同时使用两种方法-保留接口,并可以访问属性(如果可以添加新接口):

public interface ISessionWithServerUri : ISession { // Come up with a better name
    Uri ServerUri {get;}
}


现在,您的Session类可以实现ISessionWithServerUri,让您将_session的声明从Session类更改为ISessionWithServerUri接口:

internal DataClass : IDataClass
{
    private readonly ISessionWithServerUri _session;

    public DataClass(ISessionWithServerUri session)
    {
        _session = session; // Look, no cast!
    }

    // some more methods that access the internal property _session.ServerUri
    // and call methods on the session object
    // ...
}

10-08 06:56