mardi 24 novembre 2015

Custom Runtime Parameterisation of Variables in C#

I have written a .NET/C# application with a simple action structure, which allows developers to write custom actions, each of which are derived from an IAction interface as shown, simplified for clarity:

interface IAction
{
    bool Start();
}

Each action class derived from the interface above then has various custom properties as appropriate, e.g. an action might have the option to "Compress During Processing" in its action classes (derived from IAction as shown above), e.g.:

[DisplayName("Compress During Processing")]
public bool Compress { get; set; }

These values are then editable in a WinForms PropertyGrid control in the application UI, so that the users of the application can select whether to, in this instance, "Compress During Processing" when running the action.

The application allows the user to create a list of instances of these actions, and will then run them sequentially. I now have some slightly more complex requirements for the properties:

  1. To allow the values of these properties to be set based on something like environment level variables.
  2. To allow the values of these properties to be set based on the outputs of previous Actions, or the properties of previous actions.

For example, with a List { Action1, Action2, Action3, Action4 }, where the first Action is of one type derived from IAction, with the Boolean property "Compress" and the other three are of a different type derived from IAction, which has two properties, a Boolean "Archive" property and a String "Path" property, the user of the application might need to set the values of the properties as follows:

List<Action> :
  Action1 { Compress = true }
  Action2 { Archive = false, Path = "C:\tmp" }
  Action3 { Archive = [[[Action1.Compress]]], Path = [[[EnvironmentVariableSystemPath]]] }
  Action4 { Archive = true, Path = [[[ScriptVariableUserPath]]] }

During processing, when reaching Action3 and Action4, the application should check the values of the properties and set them as appropriate at runtime.

The first two Actions are already possible with the current structure, the user can easily pick the values for each property (Action1.Compress, Action2.Archive and Action2.Path) in the property grid control. However, the new requirements are that the user may also require the ability to set the value of Action3.Archive as a reference to the post processing value of in Action1.Compress, or the value of Action3.Path to an Environment Variable, Script Variable or something similar, which would allow the actions to be run with something like input variables, for instance.

I have been thinking about various approaches to this, but I don't want to introduce some kind of custom generic type that replaces the use of the standard .NET types (above, just bool and string, e.g. I don't want to have to implement some ActionProperty type, accessing its values via .Value or something similar, as this will spoil the current setup of the property grid, where, for instance, if the user wants to just set a boolean value or string path (e.g., to false or "C:\tmp" above), this can be done cleanly.

I assume that once I've found a way to store these things, the processor will just, at the start of each Action, set its values based on these references.

As you may guess from the use of the bool types, I can't just store a reference in the form of "[[[Action1.Compress]]]" or "[[[EnvironmentVariableSystemPath]]]" in the property itself, as you can't place the string "[[[Action1.Compress]]]" into a boolean variable, or any given type. I then considered the idea of adding a .NET Attribute at runtime to the values, e.g. the application would add:

[Reference("Action1.Compress")]

to

public bool Archive { get; set; }

on the Action3 class at runtime, but am not sure if this is possible, and do not now how to design this correctly. Additionally, I'd like the references, however they are stored, to be serialisable for future saving of the objects.

Can anyone advise on how to implement this?





Aucun commentaire:

Enregistrer un commentaire