2

我正在使用 C# 中的 ASP.NET MVC。我正在创建服务类。我有一个驱动程序服务接口(IDriverService)的服务接口。

它具有以下方法定义:

Driver New();

我有这个接口的两个实现,它们实现了这个方法:

Driver New()
{
   return new Driver();
}

Driver New()
{
   return new SubclassOfDriver();
}

如您所见,一种实现通过返回基本驱动程序来实现 New 方法,另一种实现是驱动程序的某些子类。

问题是通过实现接口我必须返回一个'Driver',但有时我想返回一个'SubclassOfDriver'。我可以说你应该将结果转换为你想要的驱动程序,但这是不安全的,编码器需要有关实现的信息来确定哪个驱动程序已被实例化。这样做的最佳方法是什么?

谢谢

4

4 回答 4

6

您可以使用显式接口实现有效地重载返回类型:

Driver IDriverService.New()
{
   return New(); // Calls the method below
}

public SubclassOfDriver New()
{
   return new SubclassOfDriver();
}

现在,任何只知道您的实现作为接口实现的代码都将看到显式接口实现方法,并且只期望返回类型为Driver.

任何通过具体类型引用服务的代码只会看到第二种方法,并期望返回类型为SubclassOfDriver. 例如:

SpecialFactory specialFactory = new SpecialFactory();
SubclassOfDriver subclassDriver = specialFactory.New(); // Fine
IDriverFactory generalFactory = specialFactory;
IDriver generalDriver = generalFactory.New(); // Fine
// This wouldn't compile
SubclassOfDriver invalid = generalFactory.New();

或者,您可能希望使您的界面通用:

public interface IDriverFactory<TDriver> where TDriver : Driver
{
    TDriver New();
}

public class SpecialDriverFactory : IDriverFactory<SubclassOfDriver>
{
    public SubclassOfDriver New()
    {
        return new SubclassOfDriver();
    }
}
于 2013-10-07T14:04:10.630 回答
2

问题是通过实现接口我必须返回一个Driver但有时我想返回一个SubclassOfDriver

问题不在于返回 a Driver,而在于“有时希望返回类型为SubclassOfDriver”。如果您的代码IDriverService在某些情况下需要您的实现来返回派生类型,那么您选择的抽象级别不符合您的需要。将实现隐藏在接口后面(即隐藏在SubclassOfDriver后面Driver)的原则是您永远不需要调用特定于SubclassOfDriver.

解决这个问题的一种方法是重构Driver类以包含其他方法SubclassOfDriver不可用的方法。您可以使这些方法成为可选的,让调用者测试特定子类是否实现它们。

于 2013-10-07T14:10:04.563 回答
1

SubclassOfDriver 一个Driver

没有什么不妥。

于 2013-10-07T14:02:28.713 回答
1

您可以使用泛型:

public class Driver { }
public class SubclassOfDriver : Driver { }

public interface IDriverService<T> where T : Driver
{
    T New();
}

public class SpecificService : IDriverService<Driver>
{
    public Driver New()
    {
        return ...;
    }
}

public class OtherSpecificService : IDriverService<SubclassOfDriver>
{
    public SubclassOfDriver New()
    {
        return ...;
    }
}
于 2013-10-07T14:04:53.510 回答