如何仅基于基类型创建派生对象?

时间:2016-06-13 08:11:43

标签: c# .net inheritance

例如我有这个类:

public abstract class Device 
{
    public Device()
    {
    }

    public Device(XmlDevice xmlDevice)
    {
        // creating device by xmlDevice
    }
} 

public class Modem : Device
{
    public Modem()
    {
    }

    public Modem(XmlModem modem)
    {
        // creating modem by xmlModem
    }
}

public class Plc : Device
{
    public Plc()
    {
    }

    public Plc(XmlPlc plc)
    {
        // creating plc by xmlPlc
    }
}


public abstract class XmlDevice 
{
    public XmlDevice()
    {
    }
} 

public class XmlModem : XmlDevice
{
    public XmlModem()
    {
    }
}

public class XmlPlc : XmlDevice
{
    public XmlPlc()
    {
    }
}

我有一个包含XmlDevice对象的列表 - 如何根据其类型创建Device对象?我可以这样做:

foreach( xmlDevice in xmlDevicesList )
{
    if( xmlDevice is XmlModem )
        devicesList.Add( new Modem((XmlModem)xmlDevice) );
    else if( xmlDevice is XmlPlc )
        devicesList.Add( new Plc((XmlPlc)xmlDevice) );
}

但我想避免使用“is”语句和强制转换对象。这样做更干净吗?

1 个答案:

答案 0 :(得分:4)

您对当前实施的厌恶是有根据的。我可以向你承诺,它会在你添加新设备类型的那一刻打破。更糟糕的是,编译器无法知道您希望实例类型检查是详尽无遗的,因此不会通过发出错误信号来帮助您。

如果您可以更改Xml*类,则只需在CreateDevice中引入抽象方法XmlDevice,并在派生类中重写它:

public abstract class XmlDevice
{
    // ...
    public abstract Device CreateDevice();
    // ...
}

public class XmlModem : XmlDevice
{
    // ...
    public override Device CreateDevice()
    {
        return new Modem(this);
    }
    // ...
}

现在你可以这样做:

devicesList = xmlDevicesList.ConvertAll(x => x.CreateDevice());

这种方法的最大好处可能是编译器不会让您在不实施CreateDevice方法的情况下创建新设备类型。