【问题标题】:C# - Set value of an inherited static property on child and call it depending child typeC# - 在子节点上设置继承的静态属性的值并根据子类型调用它
【发布时间】:2017-12-22 12:44:08
【问题描述】:

我正在尝试看起来像这样的东西:

class SerialEquipment
{
    private int baudrate;
    ......

    public SerialEquipment(int baudrate)
    {
        this.baudrate= baudrate;
    }

    public int Baudrate{ get => baudrate; set => baudrate= value; }
    ......

    public static void IdentifyEquipment<EquipmentType>()
    {
        int baudrate = (int)typeof(EquipmentType).GetProperty("Baudrate", BindingFlags.Static | BindingFlags.Public).GetValue(null, null);
        ........
    }
}

class EquipmentTypeA: SerialEquipment
{
    private static readonly int baudrate = 9600;
    ......
    public EquipmentTypeA() : base(baudrate) { }

    public static new int Baudrate{ get => baudrate}
    ......
}

class EquipmentTypeB : SerialEquipment
{
    private static readonly int baudrate = 38400;
    ......
    public EquipmentTypeB () : base(baudrate) { }

    public static new int Baudrate { get => baudrate }
    ......
}

但是继承的目的是避免冗余,我找不到更好的东西来使用。我找不到只有一个声明的方法。那么有没有更好的方法来实现呢?

编辑 2018 年 3 月 1 日:

使用静态识别设备的功能如下所示:

public static List<String> IdentifyEquipment<EquipmentType>()
{
    List<String> wantedEquipmentList = new List<String>();

    int baudrate = (int)typeof(EquipmentType).GetProperty("Baudrate", BindingFlags.Static | BindingFlags.Public).GetValue(null, null);
    String identificationCommand = (int)typeof(EquipmentType).GetProperty("Baudrate", BindingFlags.Static | BindingFlags.Public).GetValue(null, null);
    String correctIdentificationResponse = (String)typeof(EquipmentType).GetProperty("CorrectIdentificationResponse", BindingFlags.Static | BindingFlags.Public).GetValue(null, null);

    foreach (String aSerialPort in SerialPort.GetPortNames())
    {    
        SerialPort deviceInTest = new SerialPort(aSerialPort, baudrate);
        deviceInTest.Open();

        deviceInTest.WriteLine(identificationCommand);
        System.Threading.Thread.Sleep(50);
        string result = deviceInTest.ReadLine();

        if (result.StartsWith(correctIdentificationResponse))
        {
            wantedEquipmentList.Add(aSerialPort);
        }     
    }

    return wantedEquipmentList;
}    

这里是关于 Bruno Belmonde 解决方案的新实现:

class DeviceIdentifier
{
    private List<DeviceFactory> factories = new List<DeviceFactory>();
    public void AddDeviceType(DeviceFactory factory) => factories.Add(factory);
    public ISerialDevice BuildDeviceByIdentification(String comPort, int baudrate, String identificationCommand, String identificationResponse) => factories.FirstOrDefault(deviceFactory => IdentifyEquipment(comPort, baudrate, identificationCommand, identificationResponse))?.Builder();

    private bool IdentifyEquipment(String comPort, int baudrate, String identificationCommand, String identificationResponse)
    {
        bool foundIt = false;
        SerialPort deviceInTest = new SerialPort(comPort, baudrate);
        deviceInTest.ReadTimeout = 200;
        deviceInTest.Open();

        try
        {
            deviceInTest.WriteLine(identificationCommand);
            System.Threading.Thread.Sleep(50);
            string result = deviceInTest.ReadLine();
            if (result.StartsWith(identificationResponse))
            {
                foundIt = true;
            }
        }
        catch
        {
            //........
        }

        deviceInTest.Close();
        return foundIt;
    }
}

// MAIN
DeviceIdentifier deviceIdentifier = new DeviceIdentifier();
List<EquipmentTypeA> typeAList = new List<EquipmentTypeA>();

deviceIdentifier.AddDeviceType(new DeviceFactory
{
    Baudrate = 9600,
    IdentificationCommand = "You are ?",
    IdentificationResponse = "Type A",
    Builder = () => new EquipmentTypeA(9600)
});

foreach(String aSerialPort in SerialPort.GetPortNames())
{
    ISerialDevice identifiedObject =  deviceIdentifier.BuildDeviceByIdentification(aSerialPort, 9600, "You are ?", "Type A");

    if (identifiedObject != null)
        typeAList.Add((EquipmentTypeA)identifiedObject);
}

【问题讨论】:

  • 首先想到的问题是你打算如何使用它?答案会因用例而异。覆盖静态方法很可能是一个糟糕的选择,因为如果您有任何多态集合(或任何多态声明),它将无法工作
  • 您只有几个选项 2,3,4,6,10 用于车轮...只需为它们使用枚举... 耸耸肩
  • @BrunoBelmondo 本例中的wheelNumber 值对应于Serial Equipments(Base class)不同种类(Child class)的默认波特率。我正在使用波特率和许多其他静态属性来首先识别我正在与之交谈的设备,然后我开始使用它。
  • @KevinCook 正如我所说的,这只是一个示例,我的应用程序与车辆无关,因此我的属性可以具有随机值。此外,如果我想在不创建对象的情况下访问子类的特定值,我认为枚举不会改变任何东西,我仍然需要将其作为静态对象。
  • 如果“您正在与设备通话”,那么您很可能拥有它的实例。为什么使用静态字段而不是实例字段?这就是我需要用法来回答的地方...

标签: c# .net performance inheritance


【解决方案1】:

将您的设计更改为以下内容:

public interface IDevice
{
    void WhateverIWantToDoWIthDevice();
}

public class DeviceIdentifier
{
    private List<DeviceFactory> factories = new List<DeviceFactory>();
    public void AddDeviceType(DeviceFactory factory) => factories.Add(factory);
    public IDevice BuildDeviceFromBaudrate(int baudrate) => factories.FirstOrDefault(f => f.BaudRate == baudrate)?.Builder();
}

public class DeviceFactory
{
    public int BaudRate { get; set; }
    public Func<IDevice> Builder { get; set; }
}

然后在你的主目录中,像这样添加已知设备

deviceIdentifier.AddDeviceType(new DeviceFactory
{
    BaudRate = 12,
    Builder = () => new DeviceOfTypeA()
});

所以当连接某些东西时,您可以测试波特率与设备标识符,这将为您提供一个设备实例,假设它有一个工厂匹配。

您可以从这里详细说明识别...所需的测试

最后,请记住,静电必须小心处理,过多的静电通常是难闻的气味。静态覆盖更糟糕

【讨论】:

  • 我会尝试这个实现并告诉你。
  • 我并没有真正了解您的代码中使用的所有概念。我从来没有使用过这个对象构造过程(Builder Pattern?)。尤其是这一行:“public IDevice BuildDeviceFromBaudrate(int baudrate) => factory.FirstOrDefault(f => f.BaudRate == baudrate)?.Builder();”能详细解释一下吗?
  • 这一行正在查看所有工厂并获得第一个匹配给定波特率的工厂。然后,如果没有可用,则返回 null。否则它会调用 Builder 函数(chich 封装了对工厂持有的类型的构造函数的调用)
  • 我想我已经开始理解这个过程了,但是我该如何称呼“BuildDeviceFromBaudrate”呢?
  • 好吧,我想在你的代码中的某个地方,你观察要插入的设备然后你得到设备的有效波特率,然后你只需要调用 deviceIdentifier.BuildDeviceFromBaudrate(effectiveBaudrate)。当然你首先要创建 deviceIdentifier 并首先添加所有已知的设备
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-05
  • 2011-02-14
相关资源
最近更新 更多