Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C#.NET
Hello everyone,
 
I hope you are doing well ?
 
I would like to share you the following question:
 
Let's say we start from the following structure used to persist settings already implemented in a previous 32bits application.
 
public struct struct32bits
{
   [MarshalAs(UnmanagedType.I4)]
   public int lVersionNumber;
 
   [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)]
   public string szValue;
 
   [MarshalAs(UnmanagedType.R4)]
   public float fValue;
}
 
The objective is to be able to still load the file previously generated based on that format but afterwards convert that structure to a 64bits version.
 
public struct struct64bits
{
   public Int64 lVersionNumber;
   public string szValue;
   public float fValue;
}
 
Due to alignment issue, I found a way to loop ove the fields of the structure but when I wanted to assign the value into the new structure, I always got convertion exception.
 
public static bool Migrate32BitsStructTo64BitsStruct(ref struct32bits st32Bits, ref struct64bits st64Bits)
{
    System.Reflection.FieldInfo[] OldFields = st32Bits.GetType().GetFields(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
    System.Reflection.FieldInfo[] NewFields = st64Bits.GetType().GetFields(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
    System.Reflection.FieldInfo OldField = null;
    System.Reflection.FieldInfo NewField = null;
 
    for (int i = 0; i < OldFields.Count(); i++)
    {
        OldField = OldFields[i];
        NewField = NewFields[i];
        if (NewField != null && OldField != null)
        {
            object objValue = OldField.GetValue(st32Bits).ToString();
            try
            {
                object objNewValue = Convert.ChangeType(objValue, NewField.FieldType);
                NewField.SetValue(st64Bits, objNewValue);
            }
            catch (Exception ex)
            {
            }
        }
    }
 
    return true;
}
 
I even try with a convertion based on the new type but the assignement exception was still occured.
 
How would it be possible to apply convertion from 32 to 64 bits structure?
 
I even tried with the following modification to the structure but this was not solving the issue
 
public struct struct64bits
{
   public Int64 lVersionNumber {get; set;}
   public string szValue {get; set;}
   public float fValue {get; set;}
}
 
Does somebody have already tried something like that ?
 
What implies the 64bits structure manipulation to solve that convertion issue ?
 
Thank you very much in advance.
 
Best regards.
MiQi
Posted 20-Nov-12 9:57am
Comments
Sergey Alexandrovich Kryukov at 20-Nov-12 16:12pm
   
Is it binary persistent or text? In both cases, I see no big problem. If this is text, you are moving from smaller to bigger numeric type, so it should work as it is. With binary, the data can take different size, so you will need to preserve "32-bit type" and later do per-member clone to 64-bit. Basically, that's all. --SA
SuperMiQi at 21-Nov-12 4:09am
   
Hello Sergey, Thank you for your answer. The structure is here just basic, I have more fields to define but I wonder why the NewField.SetValue(st64Bits, objNewValue); generates me an exception. This looks to be a very nice way to apply convertion, no ?
Sergey Alexandrovich Kryukov at 21-Nov-12 12:43pm
   
Again, it all depends on what do you have for serialization... Do you have to preserve backward compatibility with already serialized data? --SA
Earloc at 20-Nov-12 16:59pm
   
where do you get what type of exception? nevertheless, if you have mapping code (Migrate32BitsStructTo64BitsStruct), why do you stick to a solution using reflection rather than copying those three values by hand, like: struct32bits source; struct64bits target; target.lVersionNumber = Convert.ToInt64(source.lVersionNumber); etc... (i think, but am not sure, that is what SA suggested?!)
SuperMiQi at 21-Nov-12 4:10am
   
Hello Earloc, Thank you for your answer. The structure is here just basic, I have more fields to define but I wonder why the NewField.SetValue(st64Bits, objNewValue); generates me an exception. This looks to be a very nice way to apply convertion, no ? That would do in an automatic way what you are proposing.
Earloc at 21-Nov-12 6:37am
   
Your welcome, see my provided solution as a possible start to solving your problem

1 solution

Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

i suggest you implement it by hand at first to check if the conversion would generally succeed. When you have this proof of concept you can implement a more generic way using reflection if you prefer this approach. the problem with such solutions is to make sure you match the corresponding fields and do the neccessary value conversions - and reflection is damn slow, so you should implement a mechanism to cache all those FieldInfos (although the performance can be considered less critical, if you deal with only a couple of instances, but thats another story)
 
if you keep to the reflection-mechanism, this could provide you with a base implementation idea:
 
private static  IDictionary<string,>    _32BitFieldsDict = null;
private static  IDictionary<string,>    _64BitFieldsDict = null;
 
private static IDictionary<string,> LoadFieldsFor(Type AIType) {
  //does not filter readonly fields
  var fieldInfos = AIType.GetType().GetFields(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
 
  var dict = new Dictionary<string,>(fieldInfos.Length);
 
  foreach (var fieldInfo in fieldInfos) {
    dict.Add(fieldInfo.Name, fieldInfo);
  }
 
  return dict;
}
 
public static bool Migrate32BitsStructTo64BitsStruct(ref struct32bits st32Bits, ref struct64bits st64Bits) {
 
  if (_32BitFieldsDict == null) //not threadsafe
    _32BitFieldsDict = LoadFieldsFor(typeof(struct32bits));
 
            
  if (_64BitFieldsDict == null) //not threadsafe
    _64BitFieldsDict = LoadFieldsFor(typeof(struct64bits));
 
  foreach (var source in _32BitFieldsDict) {
    var targetFieldInfo = _64BitFieldsDict[source.Key]; //handle possibility of finding no match
    var sourceFieldInfo = source.Value;
 
    var sourceValue =sourceFieldInfo.GetValue(st32Bits).ToString();
    var targetValue = Convert.ChangeType(sourceValue, targetFieldInfo.FieldType); //handle conversion problems
    targetFieldInfo.SetValue(st64Bits, targetValue);
 
    }
 
  return true;
}
  Permalink  

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
Your Filters
Interested
Ignored
     
0 Shai Vashdi 480
1 Tadit Dash 305
2 Sergey Alexandrovich Kryukov 250
3 Peter Leow 190
4 OriginalGriff 163
0 Sergey Alexandrovich Kryukov 9,435
1 OriginalGriff 5,498
2 Peter Leow 4,230
3 Maciej Los 3,540
4 Abhinav S 3,353


Advertise | Privacy | Mobile
Web03 | 2.8.140415.2 | Last Updated 21 Nov 2012
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Use
Layout: fixed | fluid