Tarma
Tarma

Reputation: 143

Intercept variable name in a loop

I'm creating a function for reading an integer number content in a custom object.

The custom object is contained to a wrapping class and is composed of:

public class IODBTLMNG
    {
        public int data0 = new int();
        public int data1 = new int();
        public int data2 = new int();
        public int data3 = new int();
        public int data4 = new int();
        public int data5 = new int();
        public int data6 = new int();
        public int data7 = new int();
        public int data8 = new int();
        public int data9 = new int();
        public int data10 = new int();  
    } 

I have the need in the class of use of the object, to cycle the objects "Data" and I can not use an array because the original function belonging to the dll does not allow it (wrapping class with DllExtern). The function I would like to implement should cycle the DataX fields. I write an example below:

 private int[] GetInteger()
    {
        int[] result = new int[10];

        IODBTLMNG obj = new IODBTLMNG();
        obj = PopolateObject();

        for (int i = 0; i < 11; i++)
        {
            result[i] = obj.(data + i); // The problem is this (Data i)
        }

        return result;
    }

Is it possible?

Edit:

Thanks for the answers. For integer it work. I need to complicate the question. If data isn't an integer but a class and IODBTLMNG is composed from:

public class IODBTLMNG
{
    public IODBTLMNG_data data1 = new IODBTLMNG_data();
    public IODBTLMNG_data data2 = new IODBTLMNG_data();
    public IODBTLMNG_data data3 = new IODBTLMNG_data();
    public IODBTLMNG_data data4 = new IODBTLMNG_data();
    public IODBTLMNG_data data5 = new IODBTLMNG_data();
    public IODBTLMNG_data data6 = new IODBTLMNG_data();
    public IODBTLMNG_data data7 = new IODBTLMNG_data();
    public IODBTLMNG_data data8 = new IODBTLMNG_data();
    public IODBTLMNG_data data9 = new IODBTLMNG_data();
    public IODBTLMNG_data data10 = new IODBTLMNG_data();
}

And IODBTLMNG_data is composed from:

public class IODBTLMNG_data
{
    public int T_code;
    public int life_count;
}

If I need to extract T_code, can I use reflection? Thanks

Solved Edit:

Ok...I solved using a support variable IODBTLMNG_data (obj_data) in this mode:

obj_data = (IODBTLMNG_data)(obj.GetType().GetField($"data{i}").GetValue(obj));

and:

 result[i] = obj_data.T_code;

Thanks

Upvotes: 1

Views: 202

Answers (2)

Binary Worrier
Binary Worrier

Reputation: 51719

You could wrap it in something that will give you an array/List-like accessor
You can even make it an IEnumerable so it can be used with LINQ etc

public class IODBTLMNGWrapper: IEnumerable<int>
{
    private readonly IODBTLMNG wrapped;

    public IODBTLMNGWrapper(IODBTLMNG wrapped)
    {
        this.wrapped = wrapped ?? throw new ArgumentNullException(nameof(wrapped));
    }

    public int Length { get; } = 11;

    public int this[int index]
    {
        get
        {
            switch(index)
            {
                case 0: return wrapped.data0;
                case 1: return wrapped.data1;
                case 2: return wrapped.data2;
                case 3: return wrapped.data3;
                case 4: return wrapped.data4;
                case 5: return wrapped.data5;
                case 6: return wrapped.data6;
                case 7: return wrapped.data7;
                case 8: return wrapped.data8;
                case 9: return wrapped.data9;
                case 10: return wrapped.data10;
                default:
                    throw new ArgumentOutOfRangeException($"Bad index {index}");
            }
        }
        set
        {
            switch (index)
            {
                case 0: wrapped.data0 = value; break;
                case 1: wrapped.data1 = value; break;
                case 2: wrapped.data2 = value; break;
                case 3: wrapped.data3 = value; break;
                case 4: wrapped.data4 = value; break;
                case 5: wrapped.data5 = value; break;
                case 6: wrapped.data6 = value; break;
                case 7: wrapped.data7 = value; break;
                case 8: wrapped.data8 = value; break;
                case 9: wrapped.data9 = value; break;
                case 10:wrapped.data10 = value; break;
                default:
                    throw new ArgumentOutOfRangeException($"Bad index {index}");
            }
        }
    }

    public IEnumerator<int> GetEnumerator()
    {
        for (int i = 0; i <= 10; i++)
            yield return this[i];
    }

    IEnumerator IEnumerable.GetEnumerator()
        => GetEnumerator();
}

Calling code becomes

private int[] SumItemsGreaterThan1000(IODBTLMNG data)
{
    var wrapper = IODBTLMNGWrapper(data);
    int sum = 0;
    foreach(var i in wrapper.Where(n => n > 1000)
        sum += i;
    return sum;
}

Upvotes: 0

Dmitrii Bychenko
Dmitrii Bychenko

Reputation: 186833

If you have to work with IODBTLMNG class as it is and you can't redesign it, I suggest using Reflection:

 using System.Reflection;

 ...

 result[i] = (int) (obj.GetType().GetField($"data{i + 1}").GetValue(obj));

Edit: in other words (see comments), if you want to read a public (instance) field by its name:

 var obj = ...
 string fieldName = "T_code"; // or "life_count", or "data5" - whatever

 object value = obj     // for the instance obj
   .GetType(fieldName)  // get its type (IODBTLMNG_data)
   .GetField()          // given type, find (with a help of Reflect) field description
   .GetValue(obj);      // read field's value for the obj instance

 int myResult = (int) value; // cast to int

Upvotes: 5

Related Questions