我必须通过发送命令与不同的硬件(但所有来自同一系列)进行交互。要存储命令,我之前使用的是枚举。然而,现在存在不同的hws并且取决于固件版本,除了基本命令之外还可以具有(i)新命令和/或(ii)一些基本命令的不同值。硬件实现了一个接口(我们称之为IHw
)和一个基本抽象类(HwBase
),它还提供了基本功能。
因此我想将枚举转换为具有虚拟属性的类,以便覆盖或添加功能。类似的东西:
public class CmdBase
{
public virtual int SET_LED { get { return 0x10; } }
}
public class Cmd1 : CmdBase
{
//override base command
public override int SET_LED { get { return 0x20; } }
}
public class Cmd2 : CmdBase
{
//add a functionality
public virtual int SET_LED_2 { get { return 0x30; } }
}
你认为这是正确的方法吗?如果是的话,这是使用这些命令的正确方法,以便每个hw访问自己的命令并具有某种多态性?我想也许仿制药可能有所帮助,但我不确定。我没有发布我尝试使用的尝试,而是发布了一种伪代码(这使得更容易理解),这种情况可以用于(但当然不可能)静态和静态方法可覆盖的属性:< / p>
public abstract class HwBase : IHw
{
public virtual void SetLED()
{
// base implementation should send 0x10
SendCommand(CmdBase.SET_LED);
}
}
public class Hw1 : HwBase
{
public override void SetLED()
{
// should send 0x20
SendCommand(Cmd1.SET_LED);
}
}
public class Hw2 : HwBase
{
public virtual void SetLED2()
{
// should send 0x30
SendCommand(Cmd2.SET_LED_2);
}
}
修改
我所拥有的更“真实”的例子。这是HwBase
中使用Cmd
枚举中定义的命令的方法。
protected virtual bool SetFilter()
{
if (!SendCommand(new byte[] { Cmd.SET_HP_COEF_A1, (byte)(a1Conv >> 8), (byte)(a1Conv & 0xff), 0 }) ||
!SendCommand(new byte[] { Cmd.SET_HP_COEF_B0, (byte)(b0Conv >> 8), (byte)(b0Conv & 0xff), 0 }) ||
!SendCommand(new byte[] { Cmd.SET_HP_COEF_B1, (byte)(b1Conv >> 8), (byte)(b1Conv & 0xff), 0 }) ||
!SendCommand(new byte[] { Cmd.SET_HP_COEF_D1, (byte)(d1Conv >> 8), (byte)(d1Conv & 0xff), 0 }) ||
!SendCommand(new byte[] { Cmd.SET_HP_COEF_D2, (byte)(d2Conv >> 8), (byte)(d2Conv & 0xff), 0 }) ||
!SendCommand(new byte[] { Cmd.SET_FILTER_MODE, 0, 0, 0}) )
return false;
return true;
}
然后在派生的Hw1中,根据固件版本,我可能需要与其他命令完全不同的过程。我希望除了Cmd
之外还有这些命令,但仅对Hw1
可见。现在它们位于另一个枚举CmdLegacy
中,其中包含Cmd
中定义的大多数命令(复制和粘贴)以及Cmd
中定义的一些相同命令,但具有不同的值和一些新命令(这样,如果您认为有数百个命令和几个hws,代码维护并不简单)。相反,我希望重用Cmd
中定义的命令而不在CmdLegacy
中复制和粘贴它们,而只是更改那些不同的命令并添加新的命令。
protected override bool SetFilter()
{
if (isLegacyFirmware)
{
byte msg1;
switch (filterValue)
{
default:
case 0: msg1 = CmdLegacy.FILTER_CONST_758; break;
case 1: msg1 = CmdLegacy.FILTER_CONST_1517; break;
case 2: msg1 = CmdLegacy.FILTER_CONST_3034; break;
case 3: msg1 = CmdLegacy.FILTER_CONST_6068; break;
case 4: msg1 = CmdLegacy.FILTER_CONST_12136; break;
case 5: msg1 = CmdLegacy.FILTER_CONST_24272; break;
}
byte msg2 = dataType == 0 ? CmdLegacy.UNFILTERED : CmdLegacy.FILTERED;
return SendCommand(new byte[] { CmdLegacy.SET_FILTER_MODE, msg1, msg2, 0 });
}
return base.SetFilter();
}
答案 0 :(得分:0)
您描述的对象模型如下所示:
public abstract class HwBase : IHw
{
protected void SendCommand(int x)
{
// Send the value of 'x' to the appropriate device
}
public virtual void SetLED();
}
public class Hw1 : HwBase
{
public override void SetLED()
{
// should send 0x20
base.SendCommand(0x20);
}
}
public class Hw2 : HwBase
{
public virtual void SetLED()
{
// should send 0x30
base.SendCommand(0x30);
}
}
唯一的问号是你将如何确定哪一个是目标设备。
答案 1 :(得分:0)
我决定使用泛型,即使我仍然不确定它是否是正确/更优雅的方法。在问题中给出CmdBase
,Cmd1
和Cmd2
,硬件类变为:
public abstract class HwBase<T> where T : CmdBase, new()
{
protected static readonly T Commands = new T();
public virtual void SetLED()
{
SendCommand(Commands.SET_LED); // 0x10
}
}
public class Hw1 : HwBase<Cmd1>
{
public override void SetLED()
{
SendCommand(Commands.SET_LED); // 0x20
}
}
public class Hw2 : HwBase<Cmd2>
{
public override void SetLED2()
{
SendCommand(Commands.SET_LED_2); // 0x30
}
}