Commit be034083 authored by Sam Saffron's avatar Sam Saffron

fix for crazy multi mapping ... backwards compatible - allow for the Split to be in the first type.

parent aa98265b
...@@ -504,21 +504,54 @@ class DontMap { } ...@@ -504,21 +504,54 @@ class DontMap { }
var splits = splitOn.Split(',').ToArray(); var splits = splitOn.Split(',').ToArray();
var splitIndex = 0; var splitIndex = 0;
Func<int> nextSplit = () => Func<Type,int> nextSplit = type =>
{ {
var currentSplit = splits[splitIndex]; var currentSplit = splits[splitIndex];
if (splits.Length > splitIndex + 1) if (splits.Length > splitIndex + 1)
{ {
splitIndex++; splitIndex++;
} }
bool skipFirst = false;
int startingPos = current + 1;
// if our current type has the split, skip the first time you see it.
if (type != typeof(Object))
{
var props = GetSettableProps(type);
var fields = GetSettableFields(type);
foreach (var name in props.Select(p => p.Name).Concat(fields.Select(f => f.Name)))
{
if (string.Equals(name, currentSplit, StringComparison.OrdinalIgnoreCase))
{
skipFirst = true;
startingPos = current;
break;
}
}
}
int pos; int pos;
for (pos = current + 1; pos < reader.FieldCount; pos++) for (pos = startingPos; pos < reader.FieldCount; pos++)
{ {
// some people like ID some id ... assuming case insensitive splits for now // some people like ID some id ... assuming case insensitive splits for now
if (splitOn == "*" || string.Equals(reader.GetName(pos), currentSplit, StringComparison.OrdinalIgnoreCase)) if (splitOn == "*")
{ {
break; break;
} }
if (string.Equals(reader.GetName(pos), currentSplit, StringComparison.OrdinalIgnoreCase))
{
if (skipFirst)
{
skipFirst = false;
}
else
{
break;
}
}
} }
current = pos; current = pos;
return pos; return pos;
...@@ -526,30 +559,30 @@ class DontMap { } ...@@ -526,30 +559,30 @@ class DontMap { }
var otherDeserializer = new List<object>(); var otherDeserializer = new List<object>();
int split = nextSplit(); int split = nextSplit(typeof(TFirst));
deserializer = cinfo.Deserializer = GetDeserializer<TFirst>(reader, 0, split, false); deserializer = cinfo.Deserializer = GetDeserializer<TFirst>(reader, 0, split, false);
if (typeof(TSecond) != typeof(DontMap)) if (typeof(TSecond) != typeof(DontMap))
{ {
var next = nextSplit(); var next = nextSplit(typeof(TSecond));
otherDeserializer.Add(GetDeserializer<TSecond>(reader, split, next - split, true)); otherDeserializer.Add(GetDeserializer<TSecond>(reader, split, next - split, true));
split = next; split = next;
} }
if (typeof(TThird) != typeof(DontMap)) if (typeof(TThird) != typeof(DontMap))
{ {
var next = nextSplit(); var next = nextSplit(typeof(TThird));
otherDeserializer.Add(GetDeserializer<TThird>(reader, split, next - split, true)); otherDeserializer.Add(GetDeserializer<TThird>(reader, split, next - split, true));
split = next; split = next;
} }
if (typeof(TFourth) != typeof(DontMap)) if (typeof(TFourth) != typeof(DontMap))
{ {
var next = nextSplit(); var next = nextSplit(typeof(TFourth));
otherDeserializer.Add(GetDeserializer<TFourth>(reader, split, next - split, true)); otherDeserializer.Add(GetDeserializer<TFourth>(reader, split, next - split, true));
split = next; split = next;
} }
if (typeof(TFifth) != typeof(DontMap)) if (typeof(TFifth) != typeof(DontMap))
{ {
var next = nextSplit(); var next = nextSplit(typeof(TFifth));
otherDeserializer.Add(GetDeserializer<TFifth>(reader, split, next - split, true)); otherDeserializer.Add(GetDeserializer<TFifth>(reader, split, next - split, true));
} }
...@@ -1117,6 +1150,32 @@ static readonly MethodInfo ...@@ -1117,6 +1150,32 @@ static readonly MethodInfo
.Where(p => p.GetIndexParameters().Any() && p.GetIndexParameters()[0].ParameterType == typeof(int)) .Where(p => p.GetIndexParameters().Any() && p.GetIndexParameters()[0].ParameterType == typeof(int))
.Select(p => p.GetGetMethod()).First(); .Select(p => p.GetGetMethod()).First();
class PropInfo
{
public string Name { get; set; }
public MethodInfo Setter { get; set; }
public Type Type { get; set; }
}
static List<PropInfo> GetSettableProps(Type t)
{
return t
.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.Select(p => new PropInfo
{
Name = p.Name,
Setter = p.DeclaringType == t ? p.GetSetMethod(true) : p.DeclaringType.GetProperty(p.Name).GetSetMethod(true),
Type = p.PropertyType
})
.Where(info => info.Setter != null)
.ToList();
}
static List<FieldInfo> GetSettableFields(Type t)
{
return t.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).ToList();
}
public static Func<IDataReader, T> GetClassDeserializer<T>( public static Func<IDataReader, T> GetClassDeserializer<T>(
#if CSHARP30 #if CSHARP30
IDataReader reader, int startBound, int length, bool returnNullIfFirstMissing IDataReader reader, int startBound, int length, bool returnNullIfFirstMissing
...@@ -1133,17 +1192,8 @@ static readonly MethodInfo ...@@ -1133,17 +1192,8 @@ static readonly MethodInfo
bool haveEnumLocal = false; bool haveEnumLocal = false;
il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Ldc_I4_0);
il.Emit(OpCodes.Stloc_0); il.Emit(OpCodes.Stloc_0);
var properties = typeof(T) var properties = GetSettableProps(typeof(T));
.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) var fields = GetSettableFields(typeof(T));
.Select(p => new
{
p.Name,
Setter = p.DeclaringType == typeof(T) ? p.GetSetMethod(true) : p.DeclaringType.GetProperty(p.Name).GetSetMethod(true),
Type = p.PropertyType
})
.Where(info => info.Setter != null)
.ToList();
var fields = typeof(T).GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
if (length == -1) if (length == -1)
{ {
length = reader.FieldCount - startBound; length = reader.FieldCount - startBound;
......
...@@ -1036,5 +1036,30 @@ public void TestDynamicParamNullSupport() ...@@ -1036,5 +1036,30 @@ public void TestDynamicParamNullSupport()
p.Get<int?>("@b").IsNull(); p.Get<int?>("@b").IsNull();
} }
class Foo1
{
public int Id;
public int BarId { get; set; }
}
class Bar1
{
public int BarId;
public string Name { get; set; }
}
public void TestMultiMapperIsNotConfusedWithUnorderedCols()
{
var result = connection.Query<Foo1,Bar1, Tuple<Foo1,Bar1>>("select 1 as Id, 2 as BarId, 3 as BarId, 'a' as Name", (f,b) => Tuple.Create(f,b), splitOn: "BarId").First();
result.Item1.Id.IsEqualTo(1);
result.Item1.BarId.IsEqualTo(2);
result.Item2.BarId.IsEqualTo(3);
result.Item2.Name.IsEqualTo("a");
}
} }
} }
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