Skip to content
This repository has been archived by the owner on Aug 28, 2021. It is now read-only.

Commit

Permalink
Added SpeckleError
Browse files Browse the repository at this point in the history
  • Loading branch information
teocomi committed Oct 22, 2019
1 parent ba05c4a commit 496cb1e
Show file tree
Hide file tree
Showing 3 changed files with 164 additions and 127 deletions.
272 changes: 145 additions & 127 deletions Conversion/ConverterDeserialisation.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using SpeckleCore.Data;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
Expand Down Expand Up @@ -29,6 +30,9 @@ public static List<object> Deserialise( IEnumerable<SpeckleObject> objectList, I
/// <returns>an object, a SpeckleAbstract or null.</returns>
public static object Deserialise( SpeckleObject obj, object root = null, IEnumerable<string> excludeAssebmlies = null )
{

var currentType = obj.GetType();

try
{
// null check
Expand All @@ -44,7 +48,6 @@ public static object Deserialise( SpeckleObject obj, object root = null, IEnumer
}

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

// create a list of base types for this object
Expand Down Expand Up @@ -90,170 +93,185 @@ public static object Deserialise( SpeckleObject obj, object root = null, IEnumer
}
}

// last, but not least, try and return the original object (?)
return obj;
return new SpeckleConversionError
{
Message = $"Could not convert object of type '{currentType}'",
Details = $"No Speckle kit capable of converting objects of type '{currentType}' was found, this either means we haven't developed it yet or that you're missing the required kit ¯\\_(ツ)_/¯",
SourceObject = obj
};
}
else
{
// we have a speckle abstract object
var absObj = obj as SpeckleAbstract;
return DeserializeSpeckleAbstract(obj, root);
}

}
catch (Exception e)
{
return new SpeckleConversionError
{
Message = $"Failed to convert object of type '{currentType}'",
Details = e.Message,
SourceObject = obj
};
}
}

if ( absObj._type == "ref" )
return null;
private static object DeserializeSpeckleAbstract(object obj, object root)
{
// we have a speckle abstract object
var absObj = obj as SpeckleAbstract;

//var shortName = absObj._assembly.Split( ',' )[ 0 ];
if (absObj._type == "ref")
return null;

var assembly = System.AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault( a => a.FullName == absObj._assembly );
//var shortName = absObj._assembly.Split( ',' )[ 0 ];

//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 ) );
}
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);

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);

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;

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
{
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 ((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()) });

if ( root == null )
root = myObject;
value = mySubList;
}
}
catch { }
}

var keys = absObj.Properties.Keys;
foreach ( string key in keys )
// handles dictionaries of all sorts (kind-of!)
if (value is IDictionary)
{
try
{
var prop = TryGetProperty( type, key );
var field = type.GetField( key );
var MyDict = Activator.CreateInstance(prop != null ? prop.PropertyType : field.FieldType);

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

if ( absObj.Properties[ key ] == null ) continue;
value = MyDict;
}
catch (Exception e)
{
System.Diagnostics.Debug.WriteLine(e.Message);
}
}

var value = ReadValue( absObj.Properties[ key ], root );
// guids are a pain
if ((prop != null && prop.PropertyType == typeof(Guid)) || (field != null && field.FieldType == typeof(Guid)))
value = new Guid((string)value);

// handles both hashsets and lists or whatevers
if ( value is IEnumerable && !( value is IDictionary ) && value.GetType() != typeof( string ) )
// 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
{
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 { }
prop.SetValue(myObject, value);
}

// handles dictionaries of all sorts (kind-of!)
if ( value is IDictionary )
catch
{
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;
prop.SetValue(myObject, Convert.ChangeType(value, prop.PropertyType));
}
catch ( Exception e )
catch
{
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 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
{
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
{
}
}
}
field.SetValue(absObj, value);
}
// if it is a field
else if ( field != null )
catch
{
if ( field.FieldType.IsEnum )
field.SetValue( myObject, Enum.ToObject( field.FieldType, Convert.ChangeType( value, TypeCode.Int32 ) ) );
else
try
{
try
{
field.SetValue( absObj, value );
}
catch
{
try
{
field.SetValue( myObject, Convert.ChangeType( value, field.FieldType ) );
}
catch { }
}
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;
}

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

return myObject;
}

private static object ShallowConvert( SpeckleAbstract obj )
Expand Down
18 changes: 18 additions & 0 deletions Data/SpeckleError.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SpeckleCore.Data
{
public class SpeckleError
{
public string Message { get; set; }
public string Details { get; set; }
}
public class SpeckleConversionError : SpeckleError
{
public object SourceObject { get; set; }
}
}
1 change: 1 addition & 0 deletions SpeckleCore.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
<Compile Include="Conversion\ConverterUtilities.cs" />
<Compile Include="Conversion\ConverterDeserialisation.cs" />
<Compile Include="Conversion\ConverterSerialisation.cs" />
<Compile Include="Data\SpeckleError.cs" />
<Compile Include="LocalData\Models.cs" />
<Compile Include="LocalData\SpeckleLocalContext.cs" />
<Compile Include="Models\ModelBase.cs" />
Expand Down

0 comments on commit 496cb1e

Please sign in to comment.