Skip to content

Commit

Permalink
litedb-org#1860 enum type in constructor
Browse files Browse the repository at this point in the history
  • Loading branch information
for7raid committed Nov 5, 2020
1 parent 6a767b0 commit eb34259
Show file tree
Hide file tree
Showing 2 changed files with 173 additions and 3 deletions.
154 changes: 154 additions & 0 deletions LiteDB.Tests/Issues/Issue1860_Tests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
using System;
using System.Collections.Generic;
using Xunit;
using System.Linq;

namespace LiteDB.Tests.Issues
{
public class Issue1860_Tests
{
[Fact]
public void Constructor_has_enum_bsonctor()
{
using var db = new LiteDatabase(":memory:");

// Get a collection (or create, if doesn't exist)
var col1 = db.GetCollection<C1>("c1");
var col3 = db.GetCollection<C3>("c3");

var c1 = new C1
{
Id = 1,
EnumAB = EnumAB.B
};

col1.Insert(c1);

var c3 = new C3
(
id: 1,
enumAB: EnumAB.B
);

col3.Insert(c3);

var value1 = col1.FindAll().FirstOrDefault();
Assert.NotNull(value1);
Assert.Equal(c1.EnumAB, value1.EnumAB);

var value3 = col3.FindAll().FirstOrDefault();
Assert.NotNull(value3);
Assert.Equal(c3.EnumAB, value3.EnumAB);
}

[Fact]
public void Constructor_has_enum()
{
using var db = new LiteDatabase(":memory:");

// Get a collection (or create, if doesn't exist)
var col1 = db.GetCollection<C1>("c1");
var col2 = db.GetCollection<C2>("c2");

var c1 = new C1
{
Id = 1,
EnumAB = EnumAB.B
};

col1.Insert(c1);

var c2 = new C2
(
id: 1,
enumAB: EnumAB.B
);

col2.Insert(c2);

var value1 = col1.FindAll().FirstOrDefault();
Assert.NotNull(value1);
Assert.Equal(c1.EnumAB, value1.EnumAB);

var value2 = col2.FindAll().FirstOrDefault();
Assert.NotNull(value2);
Assert.Equal(c2.EnumAB, value2.EnumAB);
}

[Fact]
public void Constructor_has_enum_asint()
{
BsonMapper.Global.EnumAsInteger = true;
using var db = new LiteDatabase(":memory:");

// Get a collection (or create, if doesn't exist)
var col1 = db.GetCollection<C1>("c1");
var col2 = db.GetCollection<C2>("c2");

var c1 = new C1
{
Id = 1,
EnumAB = EnumAB.B
};

col1.Insert(c1);

var c2 = new C2
(
id: 1,
enumAB: EnumAB.B
);

col2.Insert(c2);

var value1 = col1.FindAll().FirstOrDefault();
Assert.NotNull(value1);
Assert.Equal(c1.EnumAB, value1.EnumAB);

var value2 = col2.FindAll().FirstOrDefault();
Assert.NotNull(value2);
Assert.Equal(c2.EnumAB, value2.EnumAB);
}

public enum EnumAB
{

A = 1,
B = 2,
}

public class C1
{
public int Id { get; set; }

public EnumAB? EnumAB { get; set; }
}

public class C2
{
public int Id { get; set; }

public EnumAB EnumAB { get; set; }

public C2(int id, EnumAB enumAB)
{
Id = id;
EnumAB = enumAB;
}
}

public class C3
{
public int Id { get; set; }

public EnumAB EnumAB { get; set; }

[BsonCtor]
public C3(int id, EnumAB enumAB)
{
Id = id;
EnumAB = enumAB;
}
}
}
}
22 changes: 19 additions & 3 deletions LiteDB/Client/Mapper/BsonMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -368,9 +368,9 @@ protected virtual CreateObject GetTypeCtor(EntityMapper mapper)
var ctors = mapper.ForType.GetConstructors();

var ctor =
ctors.FirstOrDefault(x => x.GetCustomAttribute<BsonCtorAttribute>() != null && x.GetParameters().All(p => Reflection.ConvertType.ContainsKey(p.ParameterType) || _basicTypes.Contains(p.ParameterType))) ??
ctors.FirstOrDefault(x => x.GetCustomAttribute<BsonCtorAttribute>() != null && x.GetParameters().All(p => Reflection.ConvertType.ContainsKey(p.ParameterType) || _basicTypes.Contains(p.ParameterType) || p.ParameterType.GetTypeInfo().IsEnum)) ??
ctors.FirstOrDefault(x => x.GetParameters().Length == 0) ??
ctors.FirstOrDefault(x => x.GetParameters().All(p => Reflection.ConvertType.ContainsKey(p.ParameterType) || _customDeserializer.ContainsKey(p.ParameterType) || _basicTypes.Contains(p.ParameterType)));
ctors.FirstOrDefault(x => x.GetParameters().All(p => Reflection.ConvertType.ContainsKey(p.ParameterType) || _customDeserializer.ContainsKey(p.ParameterType) || _basicTypes.Contains(p.ParameterType) || p.ParameterType.GetTypeInfo().IsEnum));

if (ctor == null) return null;

Expand All @@ -397,12 +397,28 @@ protected virtual CreateObject GetTypeCtor(EntityMapper mapper)
}
else if (_basicTypes.Contains(p.ParameterType))
{
var typeExpr = Expression.Constant(p.ParameterType);
var typeExpr = Expression.Constant(p.ParameterType);
var rawValue = Expression.Property(expr, typeof(BsonValue).GetProperty("RawValue"));
var convertTypeFunc = Expression.Call(typeof(Convert).GetMethod("ChangeType", new Type[] { typeof(object), typeof(Type) }), rawValue, typeExpr);
var cast = Expression.Convert(convertTypeFunc, p.ParameterType);
pars.Add(cast);
}
else if (p.ParameterType.GetTypeInfo().IsEnum && this.EnumAsInteger)
{
var typeExpr = Expression.Constant(p.ParameterType);
var rawValue = Expression.PropertyOrField(expr, "AsInt32");
var convertTypeFunc = Expression.Call(typeof(Enum).GetMethod("ToObject", new Type[] { typeof(Type), typeof(Int32) }), typeExpr, rawValue);
var cast = Expression.Convert(convertTypeFunc, p.ParameterType);
pars.Add(cast);
}
else if (p.ParameterType.GetTypeInfo().IsEnum)
{
var typeExpr = Expression.Constant(p.ParameterType);
var rawValue = Expression.PropertyOrField(expr, "AsString");
var convertTypeFunc = Expression.Call(typeof(Enum).GetMethod("Parse", new Type[] { typeof(Type), typeof(string) }), typeExpr, rawValue);
var cast = Expression.Convert(convertTypeFunc, p.ParameterType);
pars.Add(cast);
}
else
{
var propInfo = Reflection.ConvertType[p.ParameterType];
Expand Down

0 comments on commit eb34259

Please sign in to comment.