0

我来自python新来的C#。我正在将设备库迁移到 C#。库本身包含所有设备实现并管理它的创建。这是一些python代码:

# All supported devices must be added to this list
device_table = [DeviceA, DeviceB, DeviceC, DeviceD]

def DeviceFactory(device, identifier):
    """ 
    Returns an open device for the given identifier. If there is no proper
    driver it raises an NotImplementedError. If wrong device connected to
    port a ValueError is raised
    """
    assert type(identifier) == str

    if device not in device_table:
        # Device not found in device table, so it's not implemented
        raise NotImplementedError("No device driver implemented for "
                                  "identifier {0}.".format(identifier))
    # If no identifier selected, do configuration before
    if identifier == "":
        raise AttributeError("No identifier selected.")

    # Try to open a device and then read identifier
    try:
        dev = DevIOLib.open(identifier)
        dev_identifier = dev.ask_identifier()
        dev.close()
    except Exception:
        raise DeviceError("Error opening device {0} on {1}.".format(device.name(), 
                                                                    identifier))

    # Now check if the opened device is really the right one
    if re.match(device.get_idn_regex(), dev_identifier) is not None:
        return device(identifier)

    raise ValueError("Wrong device connected to identifier {0}.".format(identifier))

Device[A-D]是 concreate 设备的实现。您现在可以创建设备:

concrete_device = DeviceFactory(DeviceC, "devicePortC")

我体验到这种模式效果很好,所以我想在C#. 如您所见,实现是非常动态的。你将如何在 C# 中实现这一点?

因此,所有设备的实现和管理都应该进入一个类库,以便在其他项目中轻松使用设备。

有没有更好的方法来解决这个问题?

在 C# 的帮助下,我可以创建以下内容

public class DeviceFactory
{
    private static List<Type> device_table = new List<Type>() { typeof(DeviceA)};

    public static Device CreateDevice(Type deviceType, string devicePort)
    {
        if (string.IsNullOrEmpty(devicePort))
        {
            throw new ArgumentException("No identifier selected.");
        }

        if (!deviceType.IsSubclassOf(typeof(Device)))
        {
            throw new ArgumentException("Device type unknown.");
        }

        if (!device_table.Contains(deviceType))
        {
            var message = string.Format("No device driver implemented for identifier {0}.", devicePort);
            throw new NotImplementedException(message);
        }

        string dev_identifier;
        DevHandle dev_handle;

        try
        {
            dev_handle = DevManager.Open(devicePort));
            dev_identifier = dev_handle.AskIdentifier();
        }
        catch (Exception)
        {
            throw new Exception(string.Format("Error opening device on {0}.", devicePort));
        }

        var idn_property =  deviceType.GetProperty("Identifier", BindingFlags.Static);

        var match = Regex.Match(dev_identifier,
                                idn_property.GetValue(null, null).ToString());

        if (match.Success)
        {
            return (VisaDevice) Activator.CreateInstance(deviceType, dev_handle);
        }
        else
        {
            dev_handle.IO.Close();
            var dev_name = deviceType.GetProperty("Name", BindingFlags.Static).GetValue(null, null).ToString();
            throw new Exception(string.Format("Wrong device connected to port {0}. " + 
                                              "Expected device {1}", devicePort, dev_name));
        }
    }
}
4

1 回答 1

2

我已经编辑了我的答案,请检查一下。这也是粗略的草图。我希望​​这对你有帮助。

namespace DeviceCreation
{
    //public enum DeviceType { DeviceA, DeviceB, DeviceC, DeviceD };
    public abstract class Device
    {
        public string Identifier { get; private set; }
        public Device(string identifier)
        {
            Identifier = identifier;
        }

        public abstract string Name();

        public virtual void Close()
        {

        }

        public string AskIdentifier()
        {
            return Identifier;   
        }

        public static string GetIdentifierPattern()
        {
            return "xyzsdfsdf";
        }
    }

    public class DeviceA : Device
    {
        public DeviceA(string identifier) : base(identifier) { }
        public override string Name()
        {
            return "DeviceA";
        }        
    }

    public class DeviceB : Device
    {
        public DeviceB(string identifier) : base(identifier) { }
        public override string Name()
        {
            return "DeviceB";
        }       

    }

    public class DeviceC : Device
    {
        public DeviceC(string identifier) : base(identifier) { }
        public override string Name()
        {
            return "DeviceC";
        }        
    }

    public class DeviceD : Device
    {
        public DeviceD(string identifier) : base(identifier) { }
        public override string Name()
        {
            return "DeviceD";
        }        
    }

    public class DeviceFactory
    {
        private static List<Type> device_table = new List<Type>() { typeof(DeviceA), typeof(DeviceB), typeof(DeviceC), typeof(DeviceD) };

        public static Device Create(Device device, string identifier)
        {
            if (!device_table.Contains(device.GetType()))
            {
                var message = string.Format("No device driver implemented for identifier {0}.", identifier);
                throw new NotImplementedException(message);
            }

            if (string.IsNullOrEmpty(identifier))
                throw new ArgumentException("No identifier selected.");

            //Try to open a device and then read identifier
            string dev_identifier;
            try
            {
                var dev = DevIOLib.Open(identifier);
                dev_identifier = dev.AskIdentifier();
                dev.Close();
            }
            catch (Exception ex)
            {
                throw new Exception(string.Format("Error opening device {0} on {1}.", device, identifier));
            }

            var match = Regex.Match(dev_identifier, Device.GetIdentifierPattern());
            if (match.Success)
            {
                var newDevice = (Device) Activator.CreateInstance(device.GetType(), dev_identifier);
                return newDevice;
            }
            else
                throw new Exception(string.Format("Wrong device connected to identifier {0}.", identifier));
        }
    }

    public static class DevIOLib
    {
        public static Device Open(string identier)
        {
            return new DeviceA(identier);
        }
    }

    public class DeviceCreationTest
    {
        public static void Main(string[] args)
        {
            var d = new DeviceA("asdfsdf");
            DeviceFactory.Create(d, "asdfsdf");

            Console.ReadKey();

        }   
    }
}
于 2013-03-09T12:14:31.037 回答