232 lines
7.7 KiB
C#
232 lines
7.7 KiB
C#
using System;
|
|
using ln.types.odb.values;
|
|
using System.Reflection;
|
|
using System.Collections.Generic;
|
|
using ln.logging;
|
|
using System.Linq;
|
|
using ln.types.odb.attributes;
|
|
|
|
namespace ln.types.odb.ng.mappings
|
|
{
|
|
|
|
public class ClassMapping : IODBMapping
|
|
{
|
|
public delegate object GetID(object o);
|
|
public delegate object SetID(object o, object id);
|
|
|
|
public Type MappedType { get; }
|
|
|
|
//public GetID getID { get; private set; } = (o) => Guid.NewGuid();
|
|
//public Type IDType { get; private set; }
|
|
|
|
List<FieldInfo> mappedFields = new List<FieldInfo>();
|
|
|
|
public ClassMapping(Type type)
|
|
{
|
|
Logging.Log(LogLevel.DEBUG, "Constructing ClassMapping for {0}",type);
|
|
|
|
MappedType = type;
|
|
AddFields(type);
|
|
}
|
|
|
|
private void AddFields(Type type)
|
|
{
|
|
foreach (FieldInfo fieldinfo in type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
|
|
{
|
|
if (fieldinfo.GetCustomAttribute<IgnoreFieldAttribute>() == null)
|
|
{
|
|
mappedFields.Add(fieldinfo);
|
|
//if (fieldinfo.GetCustomAttribute<DocumentIDAttribute>() != null)
|
|
//{
|
|
// getID = (o) => fieldinfo.GetValue(o);
|
|
// IDType = fieldinfo.FieldType;
|
|
//}
|
|
}
|
|
}
|
|
foreach (PropertyInfo propInfo in type.GetProperties(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
|
|
{
|
|
//if (propInfo.GetCustomAttribute<DocumentIDAttribute>() != null)
|
|
//{
|
|
// getID = (o) => propInfo.GetValue(o);
|
|
// IDType = propInfo.PropertyType;
|
|
//}
|
|
}
|
|
|
|
if ((type != null) && !type.IsValueType && (!typeof(object).Equals(type.BaseType)))
|
|
{
|
|
AddFields(type.BaseType);
|
|
}
|
|
}
|
|
|
|
public bool HasField(String name)
|
|
{
|
|
foreach (FieldInfo fieldInfo in mappedFields)
|
|
if (fieldInfo.Name.Equals(name))
|
|
return true;
|
|
return false;
|
|
}
|
|
|
|
public object UnmapValue(ODBMapper mapper,ODBValue oval)
|
|
{
|
|
Document document = oval as Document;
|
|
object o = Activator.CreateInstance(MappedType, true);
|
|
|
|
foreach (FieldInfo fieldInfo in mappedFields)
|
|
{
|
|
ByReferenceAttribute byReferenceAttribute = fieldInfo.GetCustomAttribute<ByReferenceAttribute>();
|
|
if (byReferenceAttribute != null)
|
|
{
|
|
// ToDo: Implement Referentiel Mapping
|
|
//Type ceType = byReferenceAttribute.ElementType ?? fieldInfo.FieldType;
|
|
//String cAlias = byReferenceAttribute.Alias ?? ceType.FullName;
|
|
|
|
//ObjectCollection objectCollection = mapper.GetStorage(ceType, cAlias);
|
|
//ODBValue refID = document[fieldInfo.Name];
|
|
//fieldInfo.SetValue(o, objectCollection.SelectByID(refID));
|
|
}
|
|
else
|
|
{
|
|
object fv = mapper.UnmapValue(fieldInfo.FieldType, document[fieldInfo.Name]);
|
|
if (!object.ReferenceEquals(fv,null))
|
|
{
|
|
Type st = fv.GetType();
|
|
if (st != fieldInfo.FieldType)
|
|
{
|
|
fv = mapper.TryImplicitMapping(fv, fieldInfo.FieldType);
|
|
st = fv.GetType();
|
|
}
|
|
if (st != fieldInfo.FieldType)
|
|
fv = Convert.ChangeType(fv, fieldInfo.FieldType);
|
|
}
|
|
if (!object.ReferenceEquals(null,fv))
|
|
fieldInfo.SetValue(o, fv);
|
|
}
|
|
}
|
|
return o;
|
|
}
|
|
|
|
public Document MapDocument(ODBMapper mapper,Guid documentID,object value)
|
|
{
|
|
Document document = new Document(documentID);
|
|
document["__asm__"] = value.GetType().Assembly.GetName().Name;
|
|
document["__type__"] = value.GetType().FullName;
|
|
|
|
foreach (FieldInfo fieldInfo in mappedFields)
|
|
{
|
|
object fv = fieldInfo.GetValue(value);
|
|
ODBValue ov = null;
|
|
|
|
if (fieldInfo.GetCustomAttribute<ByReferenceAttribute>() != null)
|
|
{
|
|
if (!object.ReferenceEquals(fv, null))
|
|
{
|
|
// ToDo: Implement referential mapping
|
|
//mapper.GetStorage(fieldInfo.FieldType).Ensure(fv);
|
|
//ov = mapper.MapValue(mapper.GetDocumentID(fv));
|
|
}
|
|
else
|
|
ov = ODBNull.Instance;
|
|
}
|
|
else
|
|
{
|
|
ov = mapper.MapValue(fv);
|
|
}
|
|
document[fieldInfo.Name] = ov;
|
|
}
|
|
return document;
|
|
}
|
|
|
|
public ODBValue MapValue(ODBMapper mapper,object value)
|
|
{
|
|
if (Object.ReferenceEquals(value, null))
|
|
return ODBNull.Instance;
|
|
|
|
return MapDocument(mapper, Guid.Empty, value);
|
|
}
|
|
|
|
public Type GetFieldType(ODBMapper mapper,string fieldName)
|
|
{
|
|
foreach (FieldInfo fieldInfo in mappedFields)
|
|
if (fieldInfo.Name.Equals(fieldName))
|
|
return fieldInfo.FieldType;
|
|
|
|
throw new KeyNotFoundException();
|
|
}
|
|
|
|
}
|
|
|
|
public class ObjectMapping : IODBMapping
|
|
{
|
|
|
|
public ODBValue MapValue(ODBMapper mapper, object value)
|
|
{
|
|
return new Document();
|
|
}
|
|
|
|
public object UnmapValue(ODBMapper mapper, ODBValue oval)
|
|
{
|
|
if (oval is Document)
|
|
{
|
|
Document document = oval as Document;
|
|
if (!document.Contains("__type__"))
|
|
return new object();
|
|
|
|
Type dType = Type.GetType(String.Format("{0}, {1}",document["__type__"].AsString, document["__asm__"].AsString)); //Assembly.Load(document["__asm__"].AsString).GetType(document["__type__"].AsString);
|
|
return mapper.UnmapValue(dType, oval);
|
|
} else if (oval is ODBList)
|
|
{
|
|
ODBList list = oval as ODBList;
|
|
Array array = (Array)mapper.UnmapValue(typeof(object[]), list);
|
|
|
|
if (array.Length > 0)
|
|
{
|
|
/* Magic: Try to find out about the arrays real element type */
|
|
HashSet<Type> eTypes = null;
|
|
|
|
foreach (object v in array)
|
|
{
|
|
HashSet<Type> myTypes = new HashSet<Type>();
|
|
|
|
Type eType = v?.GetType();
|
|
while (eType != null)
|
|
{
|
|
myTypes.Add(eType);
|
|
eType = eType.BaseType;
|
|
}
|
|
|
|
if (eTypes == null)
|
|
{
|
|
eTypes = myTypes;
|
|
}
|
|
else
|
|
{
|
|
eTypes.IntersectWith(myTypes);
|
|
}
|
|
}
|
|
|
|
foreach (Type t in eTypes.ToArray())
|
|
{
|
|
if (eTypes.Contains(t.BaseType))
|
|
eTypes.Remove(t.BaseType);
|
|
}
|
|
|
|
Type baseElementType = eTypes.First();
|
|
if (!array.GetType().GetElementType().Equals(baseElementType))
|
|
{
|
|
Array tarray = Array.CreateInstance(baseElementType, array.Length);
|
|
Array.Copy(array, tarray, array.Length);
|
|
array = tarray;
|
|
}
|
|
}
|
|
|
|
return array;
|
|
}
|
|
else
|
|
{
|
|
return oval.Value;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|