Try to map base classes for MongoDb

pull/1148/head
Halil ibrahim Kalkan 7 years ago
parent a14741d532
commit 80680a5cb6

@ -1,4 +1,7 @@
namespace System
using System.Collections.Generic;
using JetBrains.Annotations;
namespace System
{
public static class AbpTypeExtensions
{
@ -31,5 +34,36 @@
{
return targetType.IsAssignableFrom(type);
}
/// <summary>
/// Gets all base classes of this type.
/// </summary>
/// <param name="type">The type to get its base classes.</param>
/// <param name="includeObject">True, to include the standard <see cref="object"/> type in the returned array.</param>
public static Type[] GetBaseClasses(this Type type, bool includeObject = true)
{
var types = new List<Type>();
AddTypeAndBaseTypesRecursively(types, type.BaseType, includeObject);
return types.ToArray();
}
private static void AddTypeAndBaseTypesRecursively(
[NotNull] List<Type> types,
[CanBeNull] Type type,
bool includeObject)
{
if (type == null)
{
return;
}
if (!includeObject && type == typeof(object))
{
return;
}
AddTypeAndBaseTypesRecursively(types, type.BaseType, includeObject);
types.Add(type);
}
}
}

@ -1,4 +1,5 @@
using System;
using System.Reflection;
using MongoDB.Bson.Serialization;
using Volo.Abp.Data;
@ -9,34 +10,50 @@ namespace Volo.Abp.MongoDB
public static void ConfigureAbpConventions(this BsonClassMap map)
{
map.AutoMap();
map.ConfigureExtraProperties();
map.TryConfigureExtraProperties();
}
public static void ConfigureExtraProperties<TEntity>(this BsonClassMap<TEntity> map)
public static bool TryConfigureExtraProperties<TEntity>(this BsonClassMap<TEntity> map)
where TEntity : class, IHasExtraProperties
{
var property = map.ClassType.GetProperty(
nameof(IHasExtraProperties.ExtraProperties),
BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty
);
if (property?.DeclaringType != map.ClassType)
{
return false;
}
map.SetExtraElementsMember(new BsonMemberMap(
map,
typeof(TEntity).GetMember(nameof(IHasExtraProperties.ExtraProperties))[0])
);
return true;
}
/// <summary>
/// Configures SetExtraElementsMember if the <see cref="BsonClassMap.ClassType"/>
/// implements the <see cref="IHasExtraProperties"/> interface.
/// Otherwise, does nothing
/// </summary>
public static void ConfigureExtraProperties(this BsonClassMap map)
public static bool TryConfigureExtraProperties(this BsonClassMap map)
{
if (map.ClassType.IsAssignableTo<IHasExtraProperties>())
if (!map.ClassType.IsAssignableTo<IHasExtraProperties>())
{
map.SetExtraElementsMember(
new BsonMemberMap(
map,
map.ClassType.GetMember(nameof(IHasExtraProperties.ExtraProperties))[0]
)
);
return false;
}
var property = map.ClassType.GetProperty(
nameof(IHasExtraProperties.ExtraProperties),
BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty
);
if (property?.DeclaringType != map.ClassType)
{
return false;
}
map.MapExtraElementsMember(property);
return true;
}
}
}

@ -3,6 +3,7 @@ using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Volo.Abp.Domain.Entities;
namespace Volo.Abp.MongoDB
{
@ -19,24 +20,40 @@ namespace Volo.Abp.MongoDB
public MongoDbContextModel Build()
{
var entityModels = _entityModelBuilders
.Select(x => x.Value)
.Cast<IMongoEntityModel>()
.ToImmutableDictionary(x => x.EntityType, x => x);
foreach (var entityModel in entityModels.Values)
lock (SyncObj)
{
var map = entityModel.As<IHasBsonClassMap>().GetMap();
lock (SyncObj)
var entityModels = _entityModelBuilders
.Select(x => x.Value)
.Cast<IMongoEntityModel>()
.ToImmutableDictionary(x => x.EntityType, x => x);
var baseClasses = new List<Type>();
foreach (var entityModel in entityModels.Values)
{
var map = entityModel.As<IHasBsonClassMap>().GetMap();
if (!BsonClassMap.IsClassMapRegistered(map.ClassType))
{
BsonClassMap.RegisterClassMap(map);
}
baseClasses.AddRange(entityModel.EntityType.GetBaseClasses(includeObject: false));
}
}
return new MongoDbContextModel(entityModels);
baseClasses = baseClasses.Distinct().ToList();
foreach (var baseClass in baseClasses)
{
if (!BsonClassMap.IsClassMapRegistered(baseClass))
{
var map = new BsonClassMap(baseClass);
map.ConfigureAbpConventions();
BsonClassMap.RegisterClassMap(map);
}
}
return new MongoDbContextModel(entityModels);
}
}
public virtual void Entity<TEntity>(Action<IMongoEntityModelBuilder<TEntity>> buildAction = null)

@ -0,0 +1,32 @@
using Shouldly;
using Xunit;
namespace System
{
public class AbpTypeExtensions_Tests
{
[Fact]
public void GetBaseClasses()
{
var baseClasses = typeof(MyClass).GetBaseClasses(includeObject: false);
baseClasses.Length.ShouldBe(2);
baseClasses[0].ShouldBe(typeof(MyBaseClass1));
baseClasses[1].ShouldBe(typeof(MyBaseClass2));
}
public abstract class MyBaseClass1
{
}
public class MyBaseClass2 : MyBaseClass1
{
}
public class MyClass : MyBaseClass2
{
}
}
}
Loading…
Cancel
Save