C# 定义采用不同参数的接口方法

C# 定义采用不同参数的接口方法,c#,.net,oop,C#,.net,Oop,我的应用程序使用连接到PC的测量仪器。我希望能够使用来自不同供应商的类似仪器 所以我定义了一个接口: interface IMeasurementInterface { void Initialize(); void Close(); } 到目前为止还不错。在测量之前,我需要设置仪器,这意味着不同仪器的参数非常不同。因此,我想定义一个方法,该方法采用可以具有不同结构的参数: interface IMeasurementInterface {

我的应用程序使用连接到PC的测量仪器。我希望能够使用来自不同供应商的类似仪器

所以我定义了一个接口:

interface IMeasurementInterface
    {
        void Initialize();
        void Close();
    }
到目前为止还不错。在测量之前,我需要设置仪器,这意味着不同仪器的参数非常不同。因此,我想定义一个方法,该方法采用可以具有不同结构的参数:

interface IMeasurementInterface
{
    void Initialize();
    void Close();
    void Setup(object Parameters);
}

然后,我会将对象投射到我需要的任何对象。这是要走的路吗?

那可能行得通。另一种选择是在字典中传递参数。

您最好创建一个抽象的“parameters”类,该类由每个不同的instruments参数扩展。。。e、 然后使用泛型来确保将正确的参数传递给正确的类

public interface IMeasurement<PARAMTYPE> where PARAMTYPE : Parameters
{
    void Init();
    void Close();
    void Setup(PARAMTYPE p);
}

public abstract class Parameters
{

}
公共接口i测量,其中PARAMTYPE:参数
{
void Init();
无效关闭();
无效设置(p型);
}
公共抽象类参数
{
}
然后针对每个特定设备

public class DeviceOne : IMeasurement<ParametersForDeviceOne>
{
    public void Init() { }
    public void Close() { }
    public void Setup(ParametersForDeviceOne p) { }
}

public class ParametersForDeviceOne : Parameters
{

}
公共类设备One:IMeasurement
{
public void Init(){}
公共void Close(){}
public void设置(参数fordeviceone p){}
}
公共类参数ordeviceOne:参数
{
}

在我看来,这种模式可能很有用,尤其是当你打算对你的应用程序进行单元测试时

如果您要处理甚至不止一种设备类型,那么控制器+设备接口分离(使用名称vlaue对进行通信)将是一个很好的解决方案

解耦

使用名称-值对可以将代码分离为设备+控制器+应用程序代码结构

示例代码

class DeviceInterface
    {
    void Initialize(IController & Controller);
    void Close();
    bool ChangeParameter(const string & Name, const string & Value); 
    bool GetParam(string & Name, string &Value );
    }
创建每个设备实现时,应使用控制器的标识来创建,控制器可接受其命令并将其转换为实际设备命令

interface IController
   {
   Initialize(DeviceSpecific & Params);
   Close();
   bool ChangeParameter(string & Name, string & Value);
   bool ChangeParams(string & Name[], string &Value []);
   }
您的用户代码将如下所示

IController     objController = new MeasurementDevice(MeasureParram);

DeviceInterface MeasureDevice = new DeviceInterface(objController);

string Value;

MeasureDevice.GetParam("Temperature", Value);

if (ConvertStringToInt(Value) > 80)
     {
     MeasureDevice.ChangeParameter("Shutdown", "True");
     RaiseAlert();
     }
DeviceInterface类应该做的就是将命令传递给控制器。控制器应负责设备通信

界面分离的优势

防止更改

这种解耦将允许您将应用程序代码与控制器隔离。设备中的更改不会影响您的用户代码

应用程序代码的可维护性

class DeviceInterface
    {
    void Initialize(IController & Controller);
    void Close();
    bool ChangeParameter(const string & Name, const string & Value); 
    bool GetParam(string & Name, string &Value );
    }
另外,用户代码总是干净的,您只需要处理应用程序逻辑。但是,如果您定义了多个接口/创建了模板或泛型,并具有特定于控制器的多种类型的参数结构,那么您的代码中将包含大量依赖于设备的垃圾,这可能会损害可读性,并在设备/其参数发生更改时产生维护问题

易实施性

class DeviceInterface
    {
    void Initialize(IController & Controller);
    void Close();
    bool ChangeParameter(const string & Name, const string & Value); 
    bool GetParam(string & Name, string &Value );
    }
您还可以将不同的控制器实现划分到自己的项目中。此外,您的应用程序还可以使用XML文件等以更动态的方式配置命令和响应,这些文件可以与控制器类一起提供,从而使整个应用程序在本质上变得更动态

现实生活

class DeviceInterface
    {
    void Initialize(IController & Controller);
    void Close();
    bool ChangeParameter(const string & Name, const string & Value); 
    bool GetParam(string & Name, string &Value );
    }
该领域的领导者最新的生产控制器项目之一也以同样的方式工作。但是他们使用LON进行设备通信

LON?

控制器(比如空调/锅炉/风扇等)网络中使用的LON协议使用此概念与各种设备进行通信

因此,您所需要的只是一个接口,它可以与您的设备进行通信,然后使用LON将名称-值对发送给它。标准协议的使用还允许您与测量仪器之外的其他设备通话。如果您的设备使用LON,则可以使用LON的开源实现

如果您的设备不支持LON,那么您可能必须设计一些用户代码仍然在名称-值对上工作的东西,并且相反的接口将您的名称-值对转换为等效的对应COTROLL struct+,并以设备理解的方式与单个设备通信


希望这有用。

这取决于您首先要如何获取参数。如果它们被存储在数据库表或某个配置文件中,并且只需要设置值,那么传入字典可能就可以了(尽管您确实会丢失类型安全性)。如果您的安装过程将稍微复杂一点,那么我会考虑将安装过程抽象一点,并执行双重调度(将CAST操作推到新的安装类)。像这样

public interface IMeasurementInterface
{
  void Initialize();
  void Close();
  void Setup( IConfigurer config );
}

public interface IConfigurer
{
  void ApplyTo( object obj );
}

public abstract ConfigurerBase<T> : IConfigurer where T : IMeasurementInterface
{
  protected abstract void ApplyTo( T item );

  void IConfigurator.ApplyTo(object obj )
  {
    var item = obj as T;
    if( item == null )
      throw new InvalidOperationException("Configurer can't be applied to this type");
    ApplyTo(item);
  }
}
公共接口iMeasureInterface
{
void初始化();
无效关闭();
无效设置(IConfigurer配置);
}
公共接口IConfiguer
{
无效应用程序(对象对象对象);
}
公共抽象配置数据库:IConfiguer,其中T:IMeasurementInterface
{
受保护的摘要无效申请(T项);
void IConfigurator.ApplyTo(对象对象对象)
{
var项目=作为T的obj;
如果(项==null)
抛出新的InvalidOperationException(“Configurer无法应用于此类型”);
ApplyTo(项目);
}
}
这样,您就不会弄乱您的度量类层次结构(或者不提供任何实现,并且假设所有实现都会做您想要的事情)。这还意味着您可以通过传入假(或模拟)测量设备来测试设置代码


如果设置过程需要处理私有或受保护的数据,那么您可以使IConfiguer的具体实现驻留在其相应的测量类中。

我的软件必须这样做,因为我需要为金属切割机支持多种不同类型的运动控制器

您的界面具有ba