Click here to Skip to main content
12,632,234 members (29,770 online)
Rate this:
 
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 10:57am
Comments
Sergey Alexandrovich Kryukov 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 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 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 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 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 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
Top Experts
Last 24hrsThis month


Advertise | Privacy | Mobile
Web01 | 2.8.161208.2 | Last Updated 21 Nov 2012
Copyright © CodeProject, 1999-2016
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100