0

我正在重新设计用于数据采集的应用程序。 我们有所谓Sensor的基类,这是或多或少如下:设计多态子类,以便在不重新部署的情况下轻松添加新子类

public abstract class Sensor 
{ 
    public virtual String Name { get; } 
    public virtual UnitOfMeasurement Unit { get; } 
    public virtual int SamplingRate { get; } 
    public virtual CalibrationModel Calibration { get; } 
} 

每个它的子类的具有用于每个属性是“硬编码的”值。例如,EmgSensor有“EMG”作为名称,“UnitOfMeasurement.Volt”作为单位等。

我们目前的系统有这个问题我正试图解决:每当一个新的实际传感器硬件开发并添加到我们的我们需要做下面的“霰弹枪手术”:

  1. 创建一个新的Sensor子类;
  2. 对系统的其他部分进行一些分散的小改动(由于依赖性等原因);
  3. 向我们的客户群发布更新。

据我所知,每个物理传感器(硬件)都是一个概念单元,因此应该能够“插入”到正在运行的系统,以便它不需要重新编译。另一方面,如果Sensor的每个子类型都被认为是一个类,那么我怎样才能从配置文件创建一个“动态”类?我应该使用工厂模式吗?有没有其他更合适的方式来实现我所需要的?

我正在使用C#(尽管我认为这是偶然的问题)。

回答

1

.NET使动态加载类型变得非常简单。我所做的只是定义一个文件夹,在其中放置包含新传感器的组件。我有一个装载器类加载文件夹中的程序集,然后检查它们是否有传感器的子类,创建子类的实例并将它们返回到列表中。

的CoreLibrary组件保持抽象基类(和其他任何需要)

namespace CoreLibrary 
{ 
    public abstract class Sensor 
    { 
     public abstract String Name { get; } 
     public abstract UnitOfMeasurement Unit { get; } 
     public abstract int SamplingRate { get; } 
     public abstract CalibrationModel Calibration { get; } 
    } 
} 

DynamicClassLoader中是具有装载的类,它有趣的东西组装。它引用了CoreLibrary ...

using System; 
using System.Collections.Generic; 
using System.IO; 
using System.Linq; 
using System.Reflection; 
using System.Configuration; 
using CoreLibrary; 

namespace DynamicClassLoader 
{ 
    public class Loader 
    { 
     public List<Sensor> LoadDynamicSensors() 
     { 
      var sensors = new List<Sensor>(); 
      if (!Directory.Exists(DynamicAssemblyFolder)) 
      { 
       return sensors; 
      } 
      var dllFileNames = Directory.GetFiles(DynamicAssemblyFolder, "*.dll"); 

      foreach (var dllFileName in dllFileNames) 
      { 
       var dynamicAssembly = Assembly.LoadFrom(dllFileName); 
       foreach (var sensorType in dynamicAssembly.GetTypes().Where(t => t.IsSubclassOf(typeof(Sensor)))) 
       { 
        var sensor = (Sensor)Activator.CreateInstance(sensorType); 
        sensors.Add(sensor); 
       } 
      } 
      return sensors; 
     } 

     public string DynamicAssemblyFolder 
     { 
      get { return ConfigurationManager.AppSettings["DynamicAssemblyFolder"]; } 
     } 
    } 
} 

然后只制作引用CoreLibrary的程序集并将它们的dll放在定义的文件夹中。例如...

using CoreLibrary; 

namespace DynamicOne 
{ 
    public class SensorA: Sensor 
    { 
     public override string Name 
     { 
      get { return "Sensor A"; } 
     } 

     public override UnitOfMeasurement Unit 
     { 
      get { return null; } 
     } 

     public override int SamplingRate 
     { 
      get { return 10; } 
     } 

     public override CalibrationModel Calibration 
     { 
      get { return null; } 
     } 
    } 
} 

并显示它适用于控制台应用程序。它只引用CoreLibrary和DynamicClassLoader。它不需要引用动态加载的程序集,因为类型都是从Sensor派生的。

using System; 
using DynamicClassLoader; 

namespace DynamicLoading 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var loader = new Loader(); 
      var sensors = loader.LoadDynamicSensors(); 
      Console.WriteLine(loader.DynamicAssemblyFolder); 
      foreach (var sensor in sensors) 
      { 
       Console.WriteLine(sensor.Name); 
      } 
      Console.Read(); 
     } 
    } 
} 

当需要新类型时。创建一个新程序集,将其放入指定的文件夹并重新启动应用程序,新传感器已加载并准备就绪。 (你可能会喜欢一个文件观察器并自动执行,但这可能是过度的。)

不确定如何使用传感器,一旦你有他们,但你可以在工厂包装(或注入)装载机,以便轻松获得特定的一个。

相关问题