0

I have a QoL problem that i can figure out myself. See my below code with some explenations

public void UpdateStock(long? instID, float? Value, int counter,string KpiName)
    {
        {
            List<KpiReturn> updateKpi = new List<KpiReturn>();
            updateKpi.Add(new KpiReturn { instID = instID, KpiName = Value });
        }
     }

And a class with my properties looking like this:

public partial class KpiReturn
{
    public long? instID { get; set; }
    public double? peValue { get; set; }
    public double? psValue { get; set; }
    public double? pbValue { get; set; }

}

This code wont work because my kpiReturn dosent have a definition for "KpiName" Right now i run 3 different if statements based on if i want the peValue,psValue,pbValue. But i want to add many more properties to this.

in the void UpdateStock code attached i have passed the string "psValue" to the KpiName.

is there any way that i can do to make the program understand that in the code

updateKpi.Add(new KpiReturn { instID = instID, KpiName = Value }

i want to pass the kpiName value instead of the actual name "kpiName"? ie psValue,pbValue or peValue

  • That simply isn't a thing you can do. The closest you might get is an indexer that does a switch internally, perhaps on an enum – Marc Gravell Oct 26 '20 at 17:54
  • Why cant you just find the right ````KpiReturn```` and modify its property? e.g. ````GetKpi(12345).psValue = 3.14159```` – Paramecium13 Oct 26 '20 at 17:59
  • It sounds a bit like your method may be doing many different things and you are using if statements to run effectively separate operations. If this is the case, you'll be happier with simpler methods that do one thing. – N-ate Oct 26 '20 at 18:04
  • Well, you could try using `dynamic` objects https://stackoverflow.com/questions/12709333/how-to-create-own-dynamic-type-or-dynamic-object-in-c But of course you will lose compile time type checking. – derpirscher Oct 26 '20 at 18:28
  • A twist on @MarcGravell's switch idea: make a `private Dictionary` inside `KpiReturn` to hold all the values, and then make all the `peValue, psValue` properties just wrappers around the `Dictionary`, using their string names as keys. Then make a constructor for `KpiReturn` that takes your string key and `double?` value, and adds them to the `Dictionary`. – Sean Skelly Oct 26 '20 at 18:51

1 Answers1

1

Sometimes it makes problems like this easier if you continue to break down the problem into smaller pieces. The right abstractions at the right level can be helpful which is the crux of @N-ate was suggesting when he mentioned breaking down the problem into smaller operations.

For example, so far you seem to have thought of the probem as requiring a big result object that holds everything. Sorta like this big ball of mud style object:

class KpiBigBallOfMudReturn
{
    public long? instId { get; set; }
    public double? peValue { get; set; }
    public double? psValue { get; set; }
    public double? pbValue { get; set; }

    // lets keep adding many more properties to
    // this class, make them nullable so we don't
    // always have to set all of them....
    // .. and more.. ...
}

But what you've also described is that you're creating values for that return separately and those things stand alone and have a name also. So if you create an abstraction around them it might look something like this:

class KpiValue
{
    public string KpiId { get; set; }
    public double Value { get; set; }
}

Here the KpiId is what you have as "KpiName" in your Update method.

@MarcGravell comment suggested using switches to select the right value based off name. Now that we have the pairs of name/values we can use a dictionary to do something similar - as @SeanSkelly suggested. We can replace the big ball of mud result object with something like this:

class KpiResult
{
    readonly IDictionary<string, double> kpiValues;

    public KpiResult(long instId, IEnumerable<KpiValue> values)
    {
        this.kpiValues = values.ToDictionary(k => k.KpiId, v => v.Value);
    }

    public double? this[string key]
    {
        get
        {
            if (this.kpiValues.TryGetValue(key, out var value))
                return value;

            return null;
        }
    }
}

Again this is just an example to illustrate the point that when you run into technical issues like this it's often helpful to see if you can solve them by making your design more SOLID

MikeJ
  • 1,299
  • 7
  • 10