예제 #1
0
        /// <summary>
        /// Deserialises a speckle object.
        /// </summary>
        /// <param name="obj"></param>
        /// <returns>an object, a SpeckleAbstract or null.</returns>
        public static object Deserialise(SpeckleObject obj, object root = null, IEnumerable <string> excludeAssebmlies = null)
        {
            try
            {
                // null check
                if (obj == null)
                {
                    return(null);
                }

                // if it's not a speckle abstract object
                if (!(obj is SpeckleAbstract))
                {
                    var typeString = obj.GetType().ToString();
                    if (toNativeMethods.ContainsKey(typeString))
                    {
                        return(toNativeMethods[typeString].Invoke(obj, new object[] { obj }));
                    }

                    var methods     = new List <MethodInfo>();
                    var currentType = obj.GetType();
                    var baseTypes   = new List <Type>();

                    // create a list of base types for this object
                    while (currentType != null)
                    {
                        baseTypes.Add(currentType);
                        currentType = currentType.BaseType;
                    }

                    var assembliesToSearch = SpeckleCore.SpeckleInitializer.GetAssemblies().Where(ass => (excludeAssebmlies != null ? !excludeAssebmlies.Contains(ass.FullName.Split(',')[0]) : true));

                    // Type first search
                    foreach (var type in baseTypes)
                    {
                        foreach (var assembly in assembliesToSearch)
                        {
                            try
                            {
                                methods.AddRange(Converter.GetExtensionMethods(assembly, type, "ToNative"));
                            }
                            catch { }
                        }
                    }

                    // iterate through the ToNative method array
                    if (methods.Count > 0)
                    {
                        foreach (var method in methods)
                        {
                            try
                            {
                                var convRes = method.Invoke(obj, new object[] { obj });
                                if (convRes != null)
                                {
                                    toNativeMethods.Add(obj.GetType().ToString(), method);
                                    return(convRes);
                                }
                            }
                            catch (Exception e)
                            {
                                // to native method failed, try another one if present!
                            }
                        }
                    }

                    // last, but not least, try and return the original object (?)
                    return(obj);
                }
                else
                {
                    // we have a speckle abstract object
                    var absObj = obj as SpeckleAbstract;

                    if (absObj._type == "ref")
                    {
                        return(null);
                    }

                    //var shortName = absObj._assembly.Split( ',' )[ 0 ];

                    var assembly = System.AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.FullName == absObj._assembly);

                    //try again, without version control
                    if (assembly == null)
                    {
                        var shortName = absObj._assembly.Split(',')[0];
                        assembly = System.AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.FullName.Contains(shortName));
                    }

                    if (assembly == null) // we can't deserialise for sure
                    {
                        return(Converter.ShallowConvert(absObj));
                    }

                    var type = assembly.GetTypes().FirstOrDefault(t => t.Name == absObj._type);
                    if (type == null) // type not present in the assembly
                    {
                        return(Converter.ShallowConvert(absObj));
                    }

                    object myObject = null;

                    try
                    {
                        var constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { }, null);
                        if (constructor != null)
                        {
                            myObject = constructor.Invoke(new object[] { });
                        }
                        if (myObject == null)
                        {
                            myObject = Activator.CreateInstance(type);
                        }
                    }
                    catch
                    {
                        myObject = System.Runtime.Serialization.FormatterServices.GetUninitializedObject(type);
                    }

                    if (myObject == null)
                    {
                        return(absObj);
                    }

                    if (root == null)
                    {
                        root = myObject;
                    }

                    var keys = absObj.Properties.Keys;
                    foreach (string key in keys)
                    {
                        var prop  = TryGetProperty(type, key);
                        var field = type.GetField(key);

                        if (prop == null && field == null)
                        {
                            continue;
                        }

                        if (absObj.Properties[key] == null)
                        {
                            continue;
                        }

                        var value = ReadValue(absObj.Properties[key], root);

                        // handles both hashsets and lists or whatevers
                        if (value is IEnumerable && !(value is IDictionary) && value.GetType() != typeof(string))
                        {
                            try
                            {
                                if ((prop != null && prop.PropertyType.IsArray) || (field != null && field.FieldType.IsArray))
                                {
                                    value = ((List <object>)value).ToArray();
                                }
                                else
                                {
                                    var mySubList = Activator.CreateInstance(prop != null ? prop.PropertyType : field.FieldType);
                                    foreach (var myObj in ((IEnumerable <object>)value))
                                    {
                                        mySubList.GetType().GetMethod("Add").Invoke(mySubList, new object[] { Convert.ChangeType(myObj, mySubList.GetType().GetGenericArguments().Single()) });
                                    }

                                    value = mySubList;
                                }
                            }
                            catch { }
                        }

                        // handles dictionaries of all sorts (kind-of!)
                        if (value is IDictionary)
                        {
                            try
                            {
                                var MyDict = Activator.CreateInstance(prop != null ? prop.PropertyType : field.FieldType);

                                foreach (DictionaryEntry kvp in ( IDictionary )value)
                                {
                                    MyDict.GetType().GetMethod("Add").Invoke(MyDict, new object[] { Convert.ChangeType(kvp.Key, MyDict.GetType().GetGenericArguments()[0]), kvp.Value });
                                }

                                value = MyDict;
                            }
                            catch (Exception e)
                            {
                                System.Diagnostics.Debug.WriteLine(e.Message);
                            }
                        }

                        // guids are a pain
                        if ((prop != null && prop.PropertyType == typeof(Guid)) || (field != null && field.FieldType == typeof(Guid)))
                        {
                            value = new Guid(( string )value);
                        }

                        // Actually set the value below, whether it's a property or field
                        // if it is a property
                        if (prop != null && prop.CanWrite)
                        {
                            if (prop.PropertyType.IsEnum)
                            {
                                prop.SetValue(myObject, Enum.ToObject(prop.PropertyType, Convert.ChangeType(value, TypeCode.Int32)));
                            }
                            else
                            {
                                try
                                {
                                    prop.SetValue(myObject, value);
                                }
                                catch
                                {
                                    try
                                    {
                                        prop.SetValue(myObject, Convert.ChangeType(value, prop.PropertyType));
                                    }
                                    catch
                                    {
                                    }
                                }
                            }
                        }
                        // if it is a field
                        else if (field != null)
                        {
                            if (field.FieldType.IsEnum)
                            {
                                field.SetValue(myObject, Enum.ToObject(field.FieldType, Convert.ChangeType(value, TypeCode.Int32)));
                            }
                            else
                            {
                                try
                                {
                                    field.SetValue(absObj, value);
                                }
                                catch
                                {
                                    try
                                    {
                                        field.SetValue(myObject, Convert.ChangeType(value, field.FieldType));
                                    }
                                    catch { }
                                }
                            }
                        }
                    }

                    //  set references too.
                    if (root == myObject)
                    {
                        Converter.ResolveRefs(absObj, myObject, "root");
                    }

                    return(myObject);
                }
            }
            catch
            {
                return(obj);
            }
        }
예제 #2
0
        /// <summary>
        /// Deserialises a speckle object.
        /// </summary>
        /// <param name="obj"></param>
        /// <returns>an object, a SpeckleAbstract or null.</returns>
        public static object Deserialise(SpeckleObject obj, object root = null)
        {
            try
            {
                // null check
                if (obj == null)
                {
                    return(null);
                }

                // if it's not a speckle abstract object
                if (!(obj is SpeckleAbstract))
                {
                    // assembly check
                    var type = obj.GetType().ToString();

                    if (toNativeMethods.ContainsKey(type))
                    {
                        return(toNativeMethods[obj.GetType().ToString()].Invoke(obj, new object[] { obj }));
                    }

                    List <Assembly> myAss = System.AppDomain.CurrentDomain.GetAssemblies().ToList().FindAll(s => s.FullName.Contains("Speckle") && s.FullName.Contains("Converter"));

                    List <MethodInfo> methods = new List <MethodInfo>();

                    foreach (var ass in myAss)
                    {
                        methods.AddRange(Converter.GetExtensionMethods(ass, obj.GetType(), "ToNative"));
                    }

                    // if we have some ToNative method
                    if (methods.Count > 0)
                    {
                        toNativeMethods.Add(type, methods[0]);
                        var result = methods[0].Invoke(obj, new object[] { obj });
                        if (result != null)
                        {
                            return(result);
                        }
                    }
                    // otherwise return null
                    return(null);
                }
                else
                {
                    // we have a speckle abstract object
                    SpeckleAbstract absObj = obj as SpeckleAbstract;

                    if (absObj._type == "ref")
                    {
                        return(null);
                    }

                    //var shortName = absObj._assembly.Split( ',' )[ 0 ];

                    var assembly = System.AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.FullName == absObj._assembly);

                    //try again
                    if (assembly == null)
                    {
                        var shortName = absObj._assembly.Split(',')[0];
                        assembly = System.AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault(a => a.FullName.Contains(shortName));
                    }

                    if (assembly == null) // we can't deserialise for sure
                    {
                        return(Converter.ShallowConvert(absObj));
                    }

                    var type = assembly.GetTypes().FirstOrDefault(t => t.Name == absObj._type);
                    if (type == null) // type not present in the assembly
                    {
                        return(Converter.ShallowConvert(absObj));
                    }

                    object myObject = null;

                    try
                    {
                        var constructor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[] { }, null);
                        if (constructor != null)
                        {
                            myObject = constructor.Invoke(new object[] { });
                        }
                        if (myObject == null)
                        {
                            myObject = Activator.CreateInstance(type);
                        }
                    }
                    catch
                    {
                        myObject = System.Runtime.Serialization.FormatterServices.GetUninitializedObject(type);
                    }

                    if (myObject == null)
                    {
                        return(null);
                    }

                    if (root == null)
                    {
                        root = myObject;
                    }

                    var keys = absObj.Properties.Keys;
                    foreach (string key in keys)
                    {
                        var prop  = TryGetProperty(type, key);
                        var field = type.GetField(key);

                        if (prop == null && field == null)
                        {
                            continue;
                        }

                        if (absObj.Properties[key] == null)
                        {
                            continue;
                        }

                        var value = ReadValue(absObj.Properties[key], root);

                        // handles both hashsets and lists or whatevers
                        if (value is IEnumerable && !(value is IDictionary) && value.GetType() != typeof(string))
                        {
                            try
                            {
                                if ((prop != null && prop.PropertyType.IsArray) || (field != null && field.FieldType.IsArray))
                                {
                                    value = ((List <object>)value).ToArray();
                                }
                                else
                                {
                                    var mySubList = Activator.CreateInstance(prop != null ? prop.PropertyType : field.FieldType);
                                    foreach (var myObj in ((IEnumerable <object>)value))
                                    {
                                        mySubList.GetType().GetMethod("Add").Invoke(mySubList, new object[] { myObj });
                                    }

                                    value = mySubList;
                                }
                            }
                            catch { }
                        }

                        // handles dictionaries of all sorts (kind-of!)
                        if (value is IDictionary)
                        {
                            try
                            {
                                var MyDict = Activator.CreateInstance(prop != null ? prop.PropertyType : field.FieldType);

                                foreach (DictionaryEntry kvp in ( IDictionary )value)
                                {
                                    MyDict.GetType().GetMethod("Add").Invoke(MyDict, new object[] { Convert.ChangeType(kvp.Key, MyDict.GetType().GetGenericArguments()[0]), kvp.Value });
                                }

                                value = MyDict;
                            }
                            catch (Exception e)
                            {
                                System.Diagnostics.Debug.WriteLine(e.Message);
                            }
                        }

                        // guids are a pain
                        if ((prop != null && prop.PropertyType == typeof(Guid)) || (field != null && field.FieldType == typeof(Guid)))
                        {
                            value = new Guid(( string )value);
                        }

                        // Actually set the value below, whether it's a property or field
                        // if it is a property
                        if (prop != null && prop.CanWrite)
                        {
                            if (prop.PropertyType.IsEnum)
                            {
                                prop.SetValue(myObject, Enum.ToObject(prop.PropertyType, Convert.ChangeType(value, TypeCode.Int32)));
                            }
                            else
                            {
                                try
                                {
                                    prop.SetValue(myObject, value);
                                }
                                catch
                                {
                                    try
                                    {
                                        prop.SetValue(myObject, Convert.ChangeType(value, prop.PropertyType));
                                    }
                                    catch
                                    {
                                    }
                                }
                            }
                        }
                        // if it is a field
                        else if (field != null)
                        {
                            if (field.FieldType.IsEnum)
                            {
                                field.SetValue(myObject, Enum.ToObject(field.FieldType, Convert.ChangeType(value, TypeCode.Int32)));
                            }
                            else
                            {
                                try
                                {
                                    field.SetValue(absObj, value);
                                }
                                catch
                                {
                                    try
                                    {
                                        field.SetValue(myObject, Convert.ChangeType(value, field.FieldType));
                                    }
                                    catch { }
                                }
                            }
                        }
                    }

                    //  set references too.
                    if (root == myObject)
                    {
                        Converter.ResolveRefs(absObj, myObject, "root");
                    }

                    return(myObject);
                }
            }
            catch
            {
                return(null);
            }
        }
예제 #3
0
        /// <summary>
        /// Deserialises a speckle object.
        /// </summary>
        /// <param name="obj"></param>
        /// <returns>an object, a SpeckleAbstract or null.</returns>
        public static object Deserialise(SpeckleObject obj, object root = null, IEnumerable <string> excludeAssebmlies = null)
        {
            var t = obj.GetType();

            try
            {
                // null check
                if (obj == null)
                {
                    return(null);
                }

                // if it's not a speckle abstract object
                if (!(obj is SpeckleAbstract))
                {
                    var typeString = obj.GetType().ToString();
                    if (toNativeMethods.ContainsKey(typeString))
                    {
                        return(toNativeMethods[typeString].Invoke(obj, new object[] { obj }));
                    }

                    var currentType = obj.GetType();
                    var methods     = new List <MethodInfo>();
                    var baseTypes   = new List <Type>();

                    // create a list of base types for this object
                    while (currentType != null)
                    {
                        baseTypes.Add(currentType);
                        currentType = currentType.BaseType;
                    }

                    var assembliesToSearch = SpeckleCore.SpeckleInitializer.GetAssemblies().Where(ass => (excludeAssebmlies != null ? !excludeAssebmlies.Contains(ass.FullName.Split(',')[0]) : true));

                    // Type first search
                    foreach (var type in baseTypes)
                    {
                        foreach (var assembly in assembliesToSearch)
                        {
                            try
                            {
                                methods.AddRange(Converter.GetExtensionMethods(assembly, type, "ToNative"));
                            }
                            catch { }
                        }
                    }

                    // iterate through the ToNative method array
                    if (methods.Count > 0)
                    {
                        Data.SpeckleException ex = null;
                        foreach (var method in methods)
                        {
                            try
                            {
                                var convRes = method.Invoke(obj, new object[] { obj });
                                if (convRes != null)
                                {
                                    toNativeMethods.Add(obj.GetType().ToString(), method);
                                    return(convRes);
                                }
                            }
                            catch (Exception e)
                            {
                                // to native method failed, try another one if present!
                                if (e.InnerException != null && e.InnerException is Data.SpeckleException)
                                {
                                    ex = e.InnerException as Data.SpeckleException;
                                }
                            }
                        }

                        if (ex != null)
                        {
                            return(new SpeckleConversionError
                            {
                                Message = $"Could not convert object of type '{t}'",
                                Details = ex.Message,
                                SourceObject = obj
                            });
                        }
                    }

                    return(new SpeckleConversionError
                    {
                        Message = $"Could not convert object of type '{t}'",
                        Details = $"No Speckle kit capable of converting objects of type '{t}' was found, this either means we haven't developed it yet or that you're missing the required kit ¯\\_(ツ)_/¯",
                        SourceObject = obj
                    });
                }
                else
                {
                    return(DeserializeSpeckleAbstract(obj, root));
                }
            }
            catch (Exception e)
            {
                return(new SpeckleConversionError
                {
                    Message = $"Failed to convert object of type '{t}'",
                    Details = e.Message,
                    SourceObject = obj
                });
            }
        }