Allow changing the properties of a mutable controller in a thread safe way I have a (control engineering) controller. These controllers usually need several parameters to do their thing, and in my application it is desirable that these parameters can be changed while the controller is running - in a thread safe and well defined manner.

I came up with this design (extremely simplified):

// This is the class that the user instanciates.
public class Controller
{
    public ControllerInfo Info { get; set; }

    public void Start() { ... }
    public void Stop() { ... }

    private ControllerBody body = new ControllerBody();

    private void ControllerThreadProc()
    {
        while (true)
        {
            var elapsedTime_ms = ...;
            var currentInfo = this.Info;
            // the actual calculation is done in another class
            this.body.SingleStep(currentInfo, elapsedTime_ms);
            Thread.Sleep(currentInfo.SampleTime_ms);
        }
    }
}

// This exists as a separate class so it is possible to test the
// mathematical model without having to do it in real-time.
public class ControllerBody
{
    public void SingleStep(ControllerInfo info, long elapsedTime_ms)
    {
        var referenceValue = info.ReferenceValueGetter();
        var calculationResult = math;
        info.ControlValueSetter(calculationResult);
    }
}

// Immutable class that contains all the info necessary to do stuff.
public class ControllerInfo
{
    public Func&lt;double&gt; ReferenceValueGetter { get; private set; }
    public Action&lt;double&gt; ControlValueSetter { get; private set; }
    public int SampleTime_ms { get; private set; }
    public double SomeConstant { get; private set; }
    public double OtherConstant { get; private set; }
    ...

    public ControllerInfo(/* 1 argument per property :( */) { /* many assignments */ }
}


Usage example:

var controller = new Controller();
controller.Info = new ControllerInfo(/* values */);
controller.Start();
// later:
controller.Info = new ControllerInfo(/* new values */);
// Application is done:
controller.Stop();


Again, it should be possible to change the controller while it is running. Therefore I gave Controller a publicly settable ControllerInfo.

However, if the user decides to change the values of SomeConstant and OtherConstant in this example, it must be guaranteed that no calculation step is executed where only one of these are changed. In other words, changing a bunch of parameters must be an atomic operation. That's why ControllerInfo is not mutable.

I have identified 2 downsides to this architecture:


If I add another mathematical constant to ControllerInfo, I have to add (1) a property, (2) a parameter to the constructor (can be forgotten even if (1) has been done!), and (3) an assigment inside the constructor (can be forgotten even if (1) and (2) have been done!).
If the user wants to change a parameter while the controller is running, they must make another tedious constructor call, passing in values that have changed, as well as values that haven't changed.


To get around the usability problem, I considered introducing a ControllerInfoFactory class, which is basically a mutable copy of ControllerInfo:

public class ControllerInfoFactory
{
    public (SamePropertiesAsControllerInfo) { get; set; }

    public ControllerInfo CreateControllerInfo()
    {
        return new ControllerInfo(/* pass all parameters from this */);
    }
}


However, that makes the first problem even worse: For each property, I now also have to add the property to ControllerInfoFactory. Luckily, this time it's not possible to forget updating the CreateControllerInfo method as long as the ControllerInfo constructor has already been updated.

Now to code review:


Does this design make sense? Is the usability OK?
Can the large amount of repetitive code per property be reduced?
Another option is to create ControllerInfo with mutable properties and a Clone method which would return a copy of the instance.

Then on the ControllerInfo Info set, simply call the Clone method and set _info to the clone of the object passed in.

private ControllerInfo _info;

public Info
{
   get { return _info; }
   set { _info = value.Clone(); }
}


To be clearer you can do away with Info as a property and instead code a method

public Controller SetInfo(ControllerInfo info)
{
     _info = info.Clone(); 
     return this;
}


Doing away with "get" semantics for Info, is a good idea, as you do not want the interface to suggest that a get followed by mutating the Info object would reflect the changes in the Controller.