/*===============================DoValueTypeFixup=============================== **Arguments: ** memberToFix -- the member in the object contained in holder being fixed up. ** holder -- the ObjectHolder for the object (a value type in this case) being completed. ** value -- the data to set into the field. ==============================================================================*/ private bool DoValueTypeFixup(FieldInfo memberToFix, ObjectHolder holder, object value) { var fieldsTemp = new FieldInfo[4]; FieldInfo[] fields = null; int currentFieldIndex = 0; int[] arrayIndex = null; ValueTypeFixupInfo currFixup = null; object fixupObj = holder.ObjectValue; ObjectHolder originalHolder = holder; Debug.Assert(holder != null, "[TypedReferenceBuilder.ctor]holder!=null"); Debug.Assert(holder.RequiresValueTypeFixup, "[TypedReferenceBuilder.ctor]holder.RequiresValueTypeFixup"); //In order to get a TypedReference, we need to get a list of all of the FieldInfos to //create the path from our outermost containing object down to the actual field which //we'd like to set. This loop is used to build up that list. while (holder.RequiresValueTypeFixup) { //Enlarge the array if required (this is actually fairly unlikely as it would require that we //be nested more than 4 deep. if ((currentFieldIndex + 1) >= fieldsTemp.Length) { var temp = new FieldInfo[fieldsTemp.Length * 2]; Array.Copy(fieldsTemp, 0, temp, 0, fieldsTemp.Length); fieldsTemp = temp; } //Get the fixup information. If we have data for our parent field, add it to our list //and continue the walk up to find the next outermost containing object. We cache the //object that we have. In most cases, we could have just grabbed it after this loop finished. //However, if the outermost containing object is an array, we need the object one further //down the chain, so we have to do a lot of caching. currFixup = holder.ValueFixup; fixupObj = holder.ObjectValue; //Save the most derived if (currFixup.ParentField != null) { FieldInfo parentField = currFixup.ParentField; ObjectHolder tempHolder = FindObjectHolder(currFixup.ContainerID); if (tempHolder.ObjectValue == null) { break; } if (Nullable.GetUnderlyingType(parentField.FieldType) != null) { fieldsTemp[currentFieldIndex] = parentField.FieldType.GetField("value", BindingFlags.NonPublic | BindingFlags.Instance); currentFieldIndex++; } fieldsTemp[currentFieldIndex] = parentField; holder = tempHolder; currentFieldIndex++; } else { //If we find an index into an array, save that information. Debug.Assert(currFixup.ParentIndex != null, "[ObjectManager.DoValueTypeFixup]currFixup.ParentIndex!=null"); holder = FindObjectHolder(currFixup.ContainerID); //find the array to fix. arrayIndex = currFixup.ParentIndex; break; } } //If the outermost container isn't an array, we need to grab it. Otherwise, we just need to hang onto //the boxed object that we already grabbed. We'll assign the boxed object back into the array as the //last step. if (!(holder.ObjectValue is Array) && holder.ObjectValue != null) { fixupObj = holder.ObjectValue; Debug.Assert(fixupObj != null, "[ObjectManager.DoValueTypeFixup]FixupObj!=null"); } if (currentFieldIndex != 0) { //MakeTypedReference requires an array of exactly the correct size that goes from the outermost object //in to the innermost field. We currently have an array of arbitrary size that goes from the innermost //object outwards. We create an array of the right size and do the copy. fields = new FieldInfo[currentFieldIndex]; for (int i = 0; i < currentFieldIndex; i++) { FieldInfo fieldInfo = fieldsTemp[(currentFieldIndex - 1 - i)]; fields[i] = fieldInfo; } Debug.Assert(fixupObj != null, "[ObjectManager.DoValueTypeFixup]fixupObj!=null"); //Make the TypedReference and use it to set the value. TypedReference typedRef = TypedReference.MakeTypedReference(fixupObj, fields); if (memberToFix != null) { memberToFix.SetValueDirect(typedRef, value); } else { TypedReference.SetTypedReference(typedRef, value); } } else if (memberToFix != null) { FormatterServices.SerializationSetValue(memberToFix, fixupObj, value); } //If we have an array index, it means that our outermost container was an array. We don't have //any way to build a TypedReference into an array, so we'll use the array functions to set the value. if (arrayIndex != null && holder.ObjectValue != null) { ((Array)(holder.ObjectValue)).SetValue(fixupObj, arrayIndex); } return true; }
public static void set_field_of_expanded (object root_object, FieldInfo [] a_fields, FieldInfo a_field, object val) // Set `a_field' with `val', an attribute reachable from `root_object' using `a_fields' as a path to // reach it. { TypedReference t = TypedReference.MakeTypedReference(root_object, a_fields); a_field.SetValueDirect(t, val); }