两个继承级别的泛型类型参数

时间:2018-03-04 22:24:35

标签: c# generics inheritance

我有一个测试仪器及其设置的基类,它们运行各种测试:

// these classes need to stay as-is
abstract class XmlSettings { }
abstract class TestInstrument<T> where T : XmlSettings { }

在一个简单的例子中,TestInstrument声明如下

sealed class LivSettings : XmlSettings { }
sealed class Liv : TestInstrument<LivSettings> { }

然而,我有一个案例,其中有一些测试仪器有很多共同点,除了一个属于其他基类的属性。该属性是一种激光。这是一个例子

// base class of lasers
abstract class LaserBase { }
// two types of lasers
sealed class Engine : LaserBase { }
sealed class Blade : LaserBase { }
// base class for laser calibration test instrument. <XmlSettings> needs to be narrowed based on type of laser
abstract class LaserCalibrationBase<T> : TestInstrument<XmlSettings> where T : LaserBase { }
// settings class for each type of laser
sealed class EngineCalibrationSettings : XmlSettings { };
sealed class BladeCalibrationSettings : XmlSettings { };
// calibration class for each type of laser
sealed class EngineCalibration : LaserCalibrationBase<Engine> { }
sealed class BladeCalibration : LaserCalibrationBase<Blade> { }

注意这个编译然而我无法指定EngineCalibrationSettingsBladeCalibrationSettings,然后在TestInstrument<XmlSettings>中使用XmlSettings代替它们。这是不对的,因为我必须将XmlSettings缩小到适当的设置类。

我想要解决可能的重复问题。我不能使用两个接口,因为每个抽象类也有具体实现的虚拟方法。

1 个答案:

答案 0 :(得分:0)

我目前使用的一种解决方法是只为所有类型的激光设置一个设置类

// base class of lasers
abstract class LaserBase { }
// two types of lasers
sealed class Engine : LaserBase { }
sealed class Blade : LaserBase { }
// base class for laser calibration test instrument. All laser types will use LaserCalibrationSettings
abstract class LaserCalibrationBase<T> : TestInstrument<LaserCalibrationSettings> where T : LaserBase { }
// settings class for all lasers
sealed class LaserCalibrationSettings : XmlSettings { };
// calibration class for each type of laser
sealed class EngineCalibration : LaserCalibrationBase<Engine> { }
sealed class BladeCalibration : LaserCalibrationBase<Blade> { }

这是有效的,因为设置类是从xml反序列化的。我可以选择仅在每个相应的设置对象中包含与每种激光类型相对应的设置,并且其他属性不会被校准类使用(但是可用,这是不可取的)

<LaserCalibrationSettings>
  <BladeName>Blade 1</BladeName>
  <!-- other settings -->
</LaserCalibrationSettings>
<LaserCalibrationSettings>
  <EngineName>Engine 1</EngineName>
  <!-- other settings -->
</LaserCalibrationSettings>

和(在vb.net中)

Public Class LaserCalibrationSettings
    Inherits XmlSettings
    <XmlElement>
    Public Property BladeName As String
    <XmlElement>
    Public Property EngineName As String
    <XmlElement> 
    Public Property OtherSettings As Whatever
End Class

VS。什么是更理想的

<EngineCalibrationSettings>
  <EngineName>Engine 1</EngineName>
  <!-- other settings -->
</EngineCalibrationSettings>
<BladeCalibrationSettings>
  <BladeName>Blade 1</BladeName>
  <!-- other settings -->
</BladeCalibrationSettings>

Public Class BladeCalibrationSettings
    Inherits XmlSettings
    <XmlElement>
    Public Property BladeName As String
    <XmlElement> 
    Public Property OtherSettings As Whatever
End Class

Public Class EngineCalibrationSettings
    Inherits XmlSettings
    <XmlElement>
    Public Property EngineName As String
    <XmlElement> 
    Public Property OtherSettings As Whatever
End Class

不可取的是,例如在EngineCalibration中,我可以访问不适用的BladeName,即

sealed class EngineCalibration : LaserCalibrationBase<Engine>
{
    public void Run()
    {
        Console.WriteLine(this.Settings.BladeName); // N/A!
    }
}

这就是为什么它只是一种解决方法。