How easy is it to copy a structure to a class if all the fields are the same?

I have a struct like this

 public struct InstrumentDefinition2 { public int instrumentId; public int Decimals; public long MinPriceIncrement_Mantissa; public short MinPriceIncrement_Exponent; public long RoundLot_Mantissa; public short RoundLot_Exponent; public char MsgType; // 'd' - Security Definition 'f' - Security Status? } [UnmanagedFunctionPointer(CallingConvention.StdCall)] public delegate void InstrumentReplayCallback(ref InstrumentDefinition2 value); 

It is built from this C ++ structure through a delegate call:

 typedef struct _InstrumentDefinition { int32_t instrumentId; int32_t Decimals; int64_t MinPriceIncrement_Mantissa; int16_t MinPriceIncrement_Exponent; int64_t RoundLot_Mantissa; int16_t RoundLot_Exponent; char MsgType; // 'd' - Security Definition 'f' - Security Status } InstrumentDefinition; 

It works great. I'm not sure if I can declare InstrumentDefinition2 as a class . But I like to declare InstrumentDefinition2 as a struct , I think of it as a "pointer to a C ++ memory block".

But during processing, I need to copy it to the class. So I want to declare a very similar C# class:

 public class InstrumentDefinition { public int instrumentId; public int Decimals; public long MinPriceIncrement_Mantissa; public short MinPriceIncrement_Exponent; public long RoundLot_Mantissa; public short RoundLot_Exponent; public char MsgType; // 'd' - Security Definition 'f' - Security Status? } 

And the question is, how can I copy InstrumentDefinition2 struct to the InstrumentDefinition class? Of course, I can assign all the fields one by one, but he:

  • I think relatively slow
  • with an error (what if a new field is introduced, and I forgot to add "handle" it?)

So can I do this anyway, without dealing with each field?

+4
source share
2 answers

If you want to copy the fields or property values โ€‹โ€‹of class instances by matching names, you can use this snippet:

 public void ShallowCopyValues<T1, T2>(T1 firstObject, T2 secondObject) { const BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public; var firstFieldDefinitions = firstObject.GetType().GetFields(bindingFlags); IEnumerable<FieldInfo> secondFieldDefinitions = secondObject.GetType().GetFields(bindingFlags); foreach (var fieldDefinition in firstFieldDefinitions) { var matchingFieldDefinition = secondFieldDefinitions.FirstOrDefault(fd => fd.Name == fieldDefinition.Name && fd.FieldType == fieldDefinition.FieldType); if (matchingFieldDefinition == null) continue; var value = fieldDefinition.GetValue(firstObject); matchingFieldDefinition.SetValue(secondObject, value); } } 

This code uses reflection to define fields with the same name and same type. If a match is found, the value is updated on the second object. In addition: this code is slower than assigning values โ€‹โ€‹one by one, but it does not matter, since usually classes do not have a large number of fields, which almost does not lead to performance loss.

Consider this code incomplete. In production code, I would definitely recommend a library like Automapper ( https://github.com/AutoMapper/AutoMapper#readme ), which is much more flexible and customizable, as mentioned by simsim.

In addition, you can map C # classes to C ++ structures, having the same layout that Matthew Watson mentions. You simply apply StructLayoutAttribute to the class, as shown in this example on MSDN: http://msdn.microsoft.com/en-us/library/795sy883.aspx The important thing is that the class in C # has the same memory format as your structure in C ++.

+3
source

To automatically copy fields / properties, I would use Automoapper , Value Injector, or something similar. In your case, copying values โ€‹โ€‹using a value injector would look like this:

 instrumentDefinition.InjectFrom(instrumentDefinition2); 

Assuming the variable names match the names of the classes and structures.

0
source

Source: https://habr.com/ru/post/1485767/


All Articles