Commit fe9b9f5a authored by vosen's avatar vosen

Improve logic for choosing constructor in type deserializator generator.

Now we choose by accessibility level, with importance: public > internal == protected > private and then by number of arguments: giving priority to the argumentless constructor.
parent adb4a35c
...@@ -1504,9 +1504,18 @@ static List<FieldInfo> GetSettableFields(Type t) ...@@ -1504,9 +1504,18 @@ static List<FieldInfo> GetSettableFields(Type t)
types[i - startBound] = reader.GetFieldType(i); types[i - startBound] = reader.GetFieldType(i);
} }
var constructors = type.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); var constructors = type.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach(ConstructorInfo ctor in constructors) bool hasDefaultConstructor = false;
foreach (ConstructorInfo ctor in constructors.OrderBy(c => c.IsPublic ? 0 : (c.IsPrivate ? 2 : 1)).ThenBy(c => c.GetParameters().Length))
{ {
ParameterInfo[] ctorParameters = ctor.GetParameters(); ParameterInfo[] ctorParameters = ctor.GetParameters();
if (ctorParameters.Length == 0)
{
il.Emit(OpCodes.Newobj, ctor);
il.Emit(OpCodes.Stloc_1);
hasDefaultConstructor = true;
break;
}
if (ctorParameters.Length != types.Length) if (ctorParameters.Length != types.Length)
continue; continue;
int i = 0; int i = 0;
...@@ -1529,15 +1538,9 @@ static List<FieldInfo> GetSettableFields(Type t) ...@@ -1529,15 +1538,9 @@ static List<FieldInfo> GetSettableFields(Type t)
break; break;
} }
} }
if(specializedConstructor == null) if (!hasDefaultConstructor && specializedConstructor == null)
{ {
var ctor = type.GetConstructor(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); throw new InvalidOperationException("A parameterless default constructor or one matching order, names and types of values returned by the query is required to allow for dapper materialization");
if (ctor == null)
{
throw new InvalidOperationException("A parameterless default constructor is required to allow for dapper materialization");
}
il.Emit(OpCodes.Newobj, ctor);
il.Emit(OpCodes.Stloc_1);
} }
} }
il.BeginExceptionBlock(); il.BeginExceptionBlock();
......
...@@ -33,6 +33,49 @@ public class ConcreteOrder : Order ...@@ -33,6 +33,49 @@ public class ConcreteOrder : Order
} }
} }
class MultipleConstructors
{
public MultipleConstructors()
{
}
public MultipleConstructors(int a, string b)
{
A = a + 1;
B = b + "!";
}
public int A { get; set; }
public string B { get; set; }
}
public void TestMultipleConstructors()
{
MultipleConstructors mult = connection.Query<MultipleConstructors>("select 0 A, 'Dapper' b").First();
mult.A.IsEqualTo(0);
mult.B.IsEqualTo("Dapper");
}
class ConstructorsWithAccessModifiers
{
private ConstructorsWithAccessModifiers()
{
}
public ConstructorsWithAccessModifiers(int a, string b)
{
A = a + 1;
B = b + "!";
}
public int A { get; set; }
public string B { get; set; }
}
public void TestConstructorsWithAccessModifiers()
{
ConstructorsWithAccessModifiers value = connection.Query<ConstructorsWithAccessModifiers>("select 0 A, 'Dapper' b").First();
value.A.IsEqualTo(1);
value.B.IsEqualTo("Dapper!");
}
class NoDefaultConstructor class NoDefaultConstructor
{ {
public NoDefaultConstructor(int a1, int? b1, float f1, string s1, Guid G1) public NoDefaultConstructor(int a1, int? b1, float f1, string s1, Guid G1)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment