jeudi 12 juillet 2018

Dependency Injection depending on DB Value

I am trying to evolve an app I wrote for my company, which handles automatic transmitter measurements like calibrations.

Until now the devices used for the measurements where "hardcoded" in the app. I.e. we had ONE device for each measurement.

Now the app should give the option to add/change/remove measuring devices and selecting which one will be used for a given measurement. This relation should be saved, in order to be able to know after a time, which device was used for a given measurement.

I am looking for patterns or best practices to achieve this, without a lot of effort.

The option I've thought about:

I have a DLL named MeasuringInstruments with some Interfaces like ICalibrator and IDmm. I also have a class for each device we own, that implement the proper interface, depending what they "can".

Each of these specific classes has a property DeviceName, which exposes the model of the device.

For persistance I am using EF6. My idea is to create a table called MeasureDevices like

 public class MeasureDevice : IEntity<int>
    {
        protected MeasureDevice() { } //Needed for EF

        public MeasureDevice(bool isActive, string name, DateTime calibrationDate)
        {
            IsActive = isActive;
            Name = string.IsNullOrEmpty(name) ? throw new ArgumentNullException(nameof(name)) : name;
            CalibrationDate = calibrationDate == default(DateTime) ? throw new ArgumentException(nameof(calibrationDate)) : calibrationDate;
        }

        public int Id { get; protected set; }

        public bool IsActive { get; set; }

        public string Name { get; protected set; }

        public DateTime CalibrationDate { get; protected set; }

        public string Company { get; protectedset; }

        public int CategoryId { get; protected set; }

        public virtual ProductCategory Category { get; protected set; }

        public void SetCalibrationDate(DateTime date)
        {
            if (date == default(DateTime) || date < CalibrationDate || date > DateTime.Now)
                throw new ArgumentException();
            CalibrationDate = date;
        }

        public void ChangeName([NotNull] string name)
        {
            if (string.IsNullOrEmpty(name) || string.IsNullOrWhiteSpace(name)) throw new ArgumentNullException(nameof(name));
            Name = name;
        }
    }

Each measurement Entity will have relations to this table.

For each device, an item is saved in the DB with the property Name being EXACTLY the same as the name of the class in MeasuringInstruments for this device.

I could do this automatically by checking which classes do implement a given interface in MeasuringInstruments and creating a MeasureDevice with correct values.

This way, I can at runtime instantiate via reflection the correct "controller" class for the device, without needing to write a check for all devices, like if(deviceName=="xxxx") DeviceController = new XXXX();

But I'm not really convinced, since any kind of change in the names, would make my app to crash.

I've tried to look for examples/open source that need to handle something like this, without effort. So I decided to ask here to know if this is an acceptable approach or maybe there is something better?





Aucun commentaire:

Enregistrer un commentaire