1

I have a list of a class MyData which holds byte arrays. I am creating a function to which I can pass List and a string to access the fields and do some operations on them - primarily concatenation.

The part I am struggling with is accessing a class field via string. I am unsure if I should be using Linq or reflection or a combination of the two.

I have a lot of data, so performance is also a consideration.

Thanks

public class MyData
{
    public byte[] vertices;
    public byte[] indicies;
}    

public byte[] ProcessData(List<MyData> inData, string fieldName)
{          
    byteArray = new byte[inData.Sum(x => x."fieldName").Length];
    offset = 0;
    for (int i = 0; i < inData.Count; i++) {
        Buffer.BlockCopy(inData[i]."fieldName", 0, ret, offset, inData[i]."fieldName".Length);
        offset += inData."fieldName".Length;
    }

    return byteArray;
}

List<MyData> AllMyData = new List<MyData>();
//Load some data (omitted) 
var AllVertices = ProcessData(AllMyData, "vertices"); 
var AllIndicies = ProcessData(AllMyData, "indicies"); 
jm358
  • 13
  • 2
  • If there are only 2 elements, why not write 2 versions `ConcatByIndex` or `ProcessVertices` to make it as simple as possible. The methods could make use of common primitives to reduce any duplicated code – Ňɏssa Pøngjǣrdenlarp Dec 04 '18 at 02:05
  • Could you please why you are looking for strings? Delegates or expression trees would be way better from performance and type safety point of view (see Klaus's answer as an example - unfortunately currently it does not fit into your question and can't be upvoted because of it) ... If you really want strings - this would be duplicate of https://stackoverflow.com/questions/1196991/get-property-value-from-string-using-reflection-in-c-sharp – Alexei Levenkov Dec 04 '18 at 03:35
  • Use of strings were a presumption on my part on how I thought it could be done and haven't had any experience with delegates. – jm358 Dec 04 '18 at 22:32
  • Property names stored as strings is not how things are often done in .Net, unless you have a Dictionary – Joel Coehoorn Dec 05 '18 at 02:13

2 Answers2

0
public byte[] ProcessData(List<MyData> inData, string fieldName)
{          
    var field = inData.GetType().GetField(fieldName);
    if (field == null)
          throw new ArgumentException("Invalid field name", nameof(fieldName));

    byte[] bytesField = field.GetValue(inData) as byte[];

    var byteArray = new byte[bytesField.Sum().Length];
    var offset = 0;

    for (int i = 0; i < inData.Count; i++) {
        Buffer.BlockCopy(bytesField[i], 0, ret, offset, bytesField.Length);
        offset += bytesField.Length;
    }

    return byteArray;
}
Nick Reshetinsky
  • 447
  • 2
  • 13
0

If would be faster (than reflection) if it is OK to represent the field selection not as string, but as function:

public byte[] ProcessData(List<MyData> inData, Func<MyData, byte[]> field)
{          
    var byteArray = new byte[inData.Sum(x => field(x).Length)];
    var offset = 0;
    for (int i = 0; i < inData.Count; i++) {
        Buffer.BlockCopy(field(inData[i]), 0, byteArray, offset, field(inData[i]).Length);
        offset += field(inData[i]).Length;
    }

    return byteArray;
}

var allVertices = ProcessData(AllMyData, x => x.vertices); 
var allIndicies = ProcessData(AllMyData, x => x.indicies);  
Klaus Gütter
  • 11,151
  • 6
  • 31
  • 36