/// <summary> /// Helper method that prepares a complex object's /// fields that are typcially serialized. It also allows /// the caller to supply a list of additional fields that /// must be serialized regardless of status. /// </summary> /// <remarks> /// Usually it is unecessary to call this as it gets /// called by <see cref="ComponentSurrogate.PreparComponentFields(object, SerializationInfo)"/>. /// </remarks> /// <param name="obj"></param> /// <param name=""></param> protected static void GatherForcedFields(object obj, SerializationInfo info, XmlSerializer serializer, params string[] forced) { //TODO: we need another version of this method that allows us to specify additional fields to add if (SerializerBase.IsReferenceNull(obj)) { return; // throw new NullReferenceException(); } Type objType = obj.GetType(); //Use reflection to get a list of all viably serializable fields. IDictionary <string, FieldInfo> fields = serializer.GetTypeFieldInfo(objType, forced); foreach (KeyValuePair <string, FieldInfo> kv in fields) { //we always want to see if the type is a complex type first, otherwise implicit casts might cause it to change to the wrong thing if (kv.Value.GetType().IsClass || kv.Value.GetType().IsAnsiClass) { info.AddValue(kv.Key, (object)kv.Value.GetValue(obj) as object); } else { info.AddValue(kv.Key, kv.Value.GetValue(obj)); } } }
/// <summary> /// Helper method that prepares a complex object's /// properties that are typcially serialized. /// </summary> /// <param name="obj"></param> /// <param name="info"></param> /// <param name="serializer"></param> protected static void GatherProperties(object obj, SerializationInfo info, XmlSerializer serializer, params string[] filter) { if (SerializerBase.IsReferenceNull(obj)) { return; // throw new NullReferenceException(); } Type objType = obj.GetType(); //Use reflection to get a list of all viably serializable fields. bool skip; IDictionary <string, PropertyInfo> fields = serializer.GetTypePropertyInfo(objType); foreach (KeyValuePair <string, PropertyInfo> kv in fields) { skip = false; if (filter != null) { for (int i = 0; i < filter.Length; i++) { if (kv.Key == filter[i]) { skip = true; } } } if (!skip) { info.AddValue(kv.Key, kv.Value.GetValue(obj, null)); } } }
/// <summary> /// Helper method that is used to push data from a SerializationInfo /// structure back into an object's fields and properties. /// </summary> /// <param name="obj"></param> /// <param name="info"></param> protected static void ReplaceState(object obj, SerializationInfo info, params string[] filter) { if (SerializerBase.IsReferenceNull(obj)) { if (obj != null) { Debug.LogWarning("An object of type: " + info.FullTypeName + " isn't initialized on the C++ side of things. This is likely due to activation of a Unity object in a way that Unity doesn't allow."); } return; //throw new NullReferenceException(); } Type objType = obj.GetType(); foreach (var entry in info) { MemberInfo[] members = objType.GetMember(entry.Name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); bool skip; foreach (var member in members) { skip = false; if (filter != null) { for (int i = 0; i < filter.Length; i++) { if (member.Name == filter[i]) { skip = true; } } } if (!skip) { try { FieldInfo field = member as FieldInfo; if (field != null) { field.SetValue(obj, entry.Value); } PropertyInfo property = member as PropertyInfo; if (property != null) { property.SetValue(obj, entry.Value, null); } } #pragma warning disable 0168 catch (ArgumentException e) { Debug.Log("<color=red>" + e.Message + " -> " + obj.GetType().Name + " from info type " + entry.Value.GetType() + "</color>"); } #pragma warning restore 0168 } } } }
/// <summary> /// Helper method that prepares info that is typcially /// serialized for MonoBehaviour components /// </summary> /// <param name="obj"></param> /// <param name="info"></param> protected static void GatherMonoBehaviourFields(object obj, SerializationInfo info, StreamingContext context) { if (SerializerBase.IsReferenceNull(obj)) { return; // throw new NullReferenceException(); } var c = obj as MonoBehaviour; var sc = context.Context as XmlSerializer.SerializeContext; if (sc != null && c != null) { Type objType = obj.GetType(); //REMOVED: This won't hurt anything here but the serializer won't make use of it. //It was too complicated of a mess to change the ObjectCache system to track //these kinds of changes. Left it here in case someone decided to //work on this feature themselves. /* * //In this case, we want to replace the element created by the serializer * //with one that was created by this surrogate. That way we can name it * //after the component. * //var element = sc.Doc.CreateElement(objType.Name); * //sc.Element = element; */ //UPDATE: This is actually usless info right now and can really screw things up if //the deserializer tries to process it. /* * //Keep a reference to the GameObject to which this component is attached. * //We might need it for during deserialization. * info.AddValue("gameObject", c.gameObject, typeof(GameObject)); */ //If this component has an 'enabled' property, we'll want to save that. PropertyInfo pi = objType.GetProperty("enabled"); if (pi != null) { info.AddValue("enabled", (bool)pi.GetValue(obj, null)); } //prepares all viably serializable fields using reflection GatherFields(c, info, sc.Serializer); //REMOVED: This tends to add too much info. //The 'enabled' property is handled above manually. //PrepareCommonProperties(c, info, sc.Serializer); } }
/// <summary> /// Helper method that prepares info that is typcially serialized for /// components /// </summary> /// <param name="obj"></param> /// <param name="info"></param> protected static void GatherFieldsAndProps(object obj, SerializationInfo info, StreamingContext context, params string[] filter) { if (SerializerBase.IsReferenceNull(obj)) { return; // throw new NullReferenceException(); } var sc = context.Context as XmlSerializer.SerializeContext; if (sc != null) { //prepares all viably serializable fields using reflection GatherFields(obj, info, sc.Serializer, filter); GatherProperties(obj, info, sc.Serializer, filter); } }
/// <summary> /// Helper method that prepares a complex object's /// properties that are typcially serialized. /// </summary> /// <param name="obj"></param> /// <param name="info"></param> /// <param name="serializer"></param> protected static void GatherProperties(object obj, SerializationInfo info, XmlSerializer serializer, params string[] filter) { if (SerializerBase.IsReferenceNull(obj)) { return; // throw new NullReferenceException(); } Type objType = obj.GetType(); //Use reflection to get a list of all viably serializable fields. bool skip; IDictionary <string, PropertyInfo> fields = serializer.GetTypePropertyInfo(objType); foreach (KeyValuePair <string, PropertyInfo> kv in fields) { skip = false; if (filter != null) { for (int i = 0; i < filter.Length; i++) { if (kv.Key == filter[i]) { skip = true; } } } if (!skip) { //we always want to see if the type is a complex type first, otherwise implicit casts might cause it to change to the wrong thing if (kv.Value.GetType().IsClass || kv.Value.GetType().IsAnsiClass) { info.AddValue(kv.Key, (object)kv.Value.GetValue(obj, null) as object); } else { info.AddValue(kv.Key, kv.Value.GetValue(obj, null)); } } } }