ln.bson/ln.bson/mapper/BsonMapper.cs

114 lines
4.5 KiB
C#

using System;
using System.Collections.Generic;
using ln.bson.mapper.mappings;
namespace ln.bson.mapper
{
public class BsonMapper
{
private static BsonMapper _defaultInstance;
public static BsonMapper DefaultInstance
{
get
{
if (_defaultInstance is null)
_defaultInstance = new BsonMapper();
return _defaultInstance;
}
}
private Dictionary<Type, BsonMapping> _bsonMappings = new Dictionary<Type, BsonMapping>();
public BsonDocument Map<T>(T o) => Map(typeof(T), o);
public BsonDocument Map(object o) => Map(o.GetType(), o);
public BsonDocument Map(Type type, object o)
{
if (TryGetMapping(type, out BsonMapping bsonMapping))
{
if (bsonMapping.TryMapValue(this, o, out BsonValue bsonValue) &&
(bsonValue is BsonDocument bsonDocument))
return bsonDocument;
throw new FormatException("could not map object to BsonDocument");
}
throw new NotSupportedException();
}
public T Unmap<T>(BsonDocument document) => (T)Unmap(typeof(T), document);
public object Unmap(Type type, BsonDocument document)
{
if (TryGetMapping(type, out BsonMapping bsonMapping) &&
bsonMapping.TryMapValue(this, document, out object o)
)
return o;
return null;
}
public bool TryGetMapping(Type type, out BsonMapping bsonMapping)
{
if (!_defaultMappings.TryGetValue(type, out bsonMapping) && !_bsonMappings.TryGetValue(type, out bsonMapping))
{
if (type.IsArray)
{
Type mappingType = typeof(ArrayMapping<>).MakeGenericType(type.GetElementType());
bsonMapping = (BsonMapping) Activator.CreateInstance(mappingType);
AddMapping(bsonMapping);
} else if (type.IsGenericType &&
type.GetGenericTypeDefinition().Equals(typeof(Dictionary<,>)) &&
type.GetGenericArguments()[0].Equals(typeof(string)))
{
Type mappingType = typeof(DictionaryMapping<>).MakeGenericType(type.GetGenericArguments()[1]);
bsonMapping = (BsonMapping)Activator.CreateInstance(mappingType);
AddMapping(bsonMapping);
} else if (type.IsGenericType &&
type.GetGenericTypeDefinition().Equals(typeof(IList<>)))
{
Type mappingType = typeof(IListMapping<,>).MakeGenericType(type, type.GetGenericArguments()[0]);
bsonMapping = (BsonMapping)Activator.CreateInstance(mappingType);
AddMapping(bsonMapping);
} else if (!type.IsPrimitive)
{
Type mappingType = typeof(ClassStructMapping<>).MakeGenericType(type);
bsonMapping = (BsonMapping) Activator.CreateInstance(mappingType);
AddMapping(bsonMapping);
} else
throw new NotSupportedException();
}
return true;
}
public void AddMapping(BsonMapping bsonMapping) => AddMapping(bsonMapping, false);
public void AddMapping(BsonMapping bsonMapping, bool replace)
{
_bsonMappings.Add(bsonMapping.SourceType, bsonMapping);
}
public BsonMapping CreateMapping<T>()
{
if (TryGetMapping(typeof(T), out BsonMapping mapping))
return mapping;
return null;
}
private static Dictionary<Type, BsonMapping> _defaultMappings = new Dictionary<Type, BsonMapping>();
public static void AddDefaultMapping(BsonMapping bsonMapping) =>
_defaultMappings.Add(bsonMapping.SourceType, bsonMapping);
static BsonMapper()
{
AddDefaultMapping(new BsonMapping.Int32());
AddDefaultMapping(new BsonMapping.Int64());
AddDefaultMapping(new BsonMapping.Double());
AddDefaultMapping(new BsonMapping.String());
AddDefaultMapping(new BsonMapping.Guid());
AddDefaultMapping(new BsonMapping.Boolean());
AddDefaultMapping(new BsonMapping.Binary());
AddDefaultMapping(new BsonMapping.DateTime());
}
}
}