Improve declarative procedure result-set binding
This commit is contained in:
@@ -5542,7 +5542,7 @@ namespace DynamORM
|
||||
|
||||
object mainResult = null;
|
||||
|
||||
if (types.Count == 0 && DynamicProcedureResultBinder.HasDeclaredResultBinding(declaredResultType))
|
||||
if (types.Count == 0 && DynamicProcedureResultBinder.CanReadResults(declaredResultType))
|
||||
{
|
||||
using (IDataReader rdr = cmd.ExecuteReader())
|
||||
using (IDataReader cache = rdr.CachedReader())
|
||||
@@ -14564,10 +14564,25 @@ namespace DynamORM
|
||||
}
|
||||
internal static class DynamicProcedureResultBinder
|
||||
{
|
||||
private sealed class ResultPropertyBinding
|
||||
private sealed class ResultMemberBinding
|
||||
{
|
||||
public ProcedureResultAttribute Attribute { get; set; }
|
||||
public PropertyInfo Property { get; set; }
|
||||
public MemberInfo Member { get; set; }
|
||||
public Type MemberType { get; set; }
|
||||
public int SortOrder { get; set; }
|
||||
|
||||
public void SetValue(object instance, object value)
|
||||
{
|
||||
PropertyInfo property = Member as PropertyInfo;
|
||||
if (property != null)
|
||||
{
|
||||
property.SetValue(instance, value, null);
|
||||
return;
|
||||
}
|
||||
FieldInfo field = Member as FieldInfo;
|
||||
if (field != null)
|
||||
field.SetValue(instance, value);
|
||||
}
|
||||
}
|
||||
internal static bool IsProcedureContract(object item)
|
||||
{
|
||||
@@ -14583,10 +14598,14 @@ namespace DynamORM
|
||||
|
||||
return iface == null ? null : iface.GetGenericArguments()[0];
|
||||
}
|
||||
internal static bool HasDeclaredResultBinding(Type resultType)
|
||||
internal static bool CanReadResults(Type resultType)
|
||||
{
|
||||
return resultType != null &&
|
||||
(typeof(IProcedureResultReader).IsAssignableFrom(resultType) || GetResultPropertyBindings(resultType).Count > 0);
|
||||
(typeof(IProcedureResultReader).IsAssignableFrom(resultType) || GetResultMemberBindings(resultType).Count > 0);
|
||||
}
|
||||
internal static bool HasDeclaredResultBinding(Type resultType)
|
||||
{
|
||||
return CanReadResults(resultType);
|
||||
}
|
||||
internal static object CreateDeclaredResult(Type resultType)
|
||||
{
|
||||
@@ -14601,14 +14620,14 @@ namespace DynamORM
|
||||
}
|
||||
internal static object ReadDeclaredResult(Type resultType, IDataReader reader)
|
||||
{
|
||||
if (!HasDeclaredResultBinding(resultType))
|
||||
if (!CanReadResults(resultType))
|
||||
throw new InvalidOperationException(string.Format("Type '{0}' does not declare a supported procedure result binding.", resultType == null ? "<null>" : resultType.FullName));
|
||||
|
||||
object instance = CreateDeclaredResult(resultType);
|
||||
|
||||
IList<ResultPropertyBinding> bindings = GetResultPropertyBindings(resultType);
|
||||
IList<ResultMemberBinding> bindings = GetResultMemberBindings(resultType);
|
||||
if (bindings.Count > 0)
|
||||
BindResultProperties(instance, reader, bindings);
|
||||
BindResultMembers(instance, reader, bindings);
|
||||
else
|
||||
((IProcedureResultReader)instance).ReadResults(reader);
|
||||
|
||||
@@ -14637,21 +14656,35 @@ namespace DynamORM
|
||||
|
||||
return payload.ToDynamic();
|
||||
}
|
||||
private static IList<ResultPropertyBinding> GetResultPropertyBindings(Type resultType)
|
||||
private static IList<ResultMemberBinding> GetResultMemberBindings(Type resultType)
|
||||
{
|
||||
return resultType.GetProperties(BindingFlags.Instance | BindingFlags.Public)
|
||||
var properties = resultType.GetProperties(BindingFlags.Instance | BindingFlags.Public)
|
||||
.Where(x => x.CanWrite && x.GetIndexParameters().Length == 0)
|
||||
.Select(x => new ResultPropertyBinding
|
||||
.Select(x => new ResultMemberBinding
|
||||
{
|
||||
Property = x,
|
||||
Member = x,
|
||||
MemberType = x.PropertyType,
|
||||
SortOrder = x.MetadataToken,
|
||||
Attribute = x.GetCustomAttributes(typeof(ProcedureResultAttribute), true).Cast<ProcedureResultAttribute>().FirstOrDefault()
|
||||
})
|
||||
});
|
||||
|
||||
var fields = resultType.GetFields(BindingFlags.Instance | BindingFlags.Public)
|
||||
.Where(x => !x.IsInitOnly && !x.IsLiteral)
|
||||
.Select(x => new ResultMemberBinding
|
||||
{
|
||||
Member = x,
|
||||
MemberType = x.FieldType,
|
||||
SortOrder = x.MetadataToken,
|
||||
Attribute = x.GetCustomAttributes(typeof(ProcedureResultAttribute), true).Cast<ProcedureResultAttribute>().FirstOrDefault()
|
||||
});
|
||||
|
||||
return properties.Concat(fields)
|
||||
.Where(x => x.Attribute != null)
|
||||
.OrderBy(x => x.Attribute.ResultIndex)
|
||||
.ThenBy(x => x.Property.MetadataToken)
|
||||
.ThenBy(x => x.SortOrder)
|
||||
.ToList();
|
||||
}
|
||||
private static void BindResultProperties(object instance, IDataReader reader, IList<ResultPropertyBinding> bindings)
|
||||
private static void BindResultMembers(object instance, IDataReader reader, IList<ResultMemberBinding> bindings)
|
||||
{
|
||||
ValidateBindings(instance.GetType(), bindings);
|
||||
|
||||
@@ -14660,7 +14693,7 @@ namespace DynamORM
|
||||
|
||||
for (int i = 0; i < bindings.Count; i++)
|
||||
{
|
||||
ResultPropertyBinding binding = bindings[i];
|
||||
ResultMemberBinding binding = bindings[i];
|
||||
while (hasCurrent && currentIndex < binding.Attribute.ResultIndex)
|
||||
{
|
||||
hasCurrent = reader.NextResult();
|
||||
@@ -14669,8 +14702,8 @@ namespace DynamORM
|
||||
if (!hasCurrent || currentIndex != binding.Attribute.ResultIndex)
|
||||
break;
|
||||
|
||||
object value = ReadResultValue(binding.Property.PropertyType, binding.Attribute, reader);
|
||||
binding.Property.SetValue(instance, value, null);
|
||||
object value = ReadResultValue(binding.MemberType, binding.Attribute, reader);
|
||||
binding.SetValue(instance, value);
|
||||
|
||||
if (i + 1 < bindings.Count)
|
||||
{
|
||||
@@ -14679,7 +14712,7 @@ namespace DynamORM
|
||||
}
|
||||
}
|
||||
}
|
||||
private static void ValidateBindings(Type resultType, IList<ResultPropertyBinding> bindings)
|
||||
private static void ValidateBindings(Type resultType, IList<ResultMemberBinding> bindings)
|
||||
{
|
||||
var duplicates = bindings.GroupBy(x => x.Attribute.ResultIndex).FirstOrDefault(x => x.Count() > 1);
|
||||
if (duplicates != null)
|
||||
@@ -14709,6 +14742,7 @@ namespace DynamORM
|
||||
}
|
||||
private static object ReadSimpleValue(Type propertyType, ProcedureResultAttribute attr, IDataReader reader)
|
||||
{
|
||||
Type targetType = Nullable.GetUnderlyingType(propertyType) ?? propertyType;
|
||||
object value = null;
|
||||
int ordinal = -1;
|
||||
bool haveRow = false;
|
||||
@@ -14725,17 +14759,21 @@ namespace DynamORM
|
||||
if (!haveRow || value == null)
|
||||
return propertyType.GetDefaultValue();
|
||||
|
||||
if (propertyType == typeof(Guid))
|
||||
if (targetType == typeof(Guid))
|
||||
{
|
||||
Guid g;
|
||||
if (Guid.TryParse(value.ToString(), out g))
|
||||
return g;
|
||||
return propertyType == typeof(Guid) ? (object)g : new Guid?(g);
|
||||
return propertyType.GetDefaultValue();
|
||||
}
|
||||
return propertyType.CastObject(value);
|
||||
if (targetType.IsEnum)
|
||||
return Enum.ToObject(targetType, value);
|
||||
|
||||
return targetType == propertyType ? propertyType.CastObject(value) : targetType.CastObject(value);
|
||||
}
|
||||
private static object ReadSimpleList(Type propertyType, Type elementType, ProcedureResultAttribute attr, IDataReader reader)
|
||||
{
|
||||
Type targetElementType = Nullable.GetUnderlyingType(elementType) ?? elementType;
|
||||
Type listType = typeof(List<>).MakeGenericType(elementType);
|
||||
var list = (System.Collections.IList)Activator.CreateInstance(listType);
|
||||
int ordinal = -1;
|
||||
@@ -14754,13 +14792,18 @@ namespace DynamORM
|
||||
continue;
|
||||
}
|
||||
object value = reader[ordinal];
|
||||
if (elementType == typeof(Guid))
|
||||
if (targetElementType == typeof(Guid))
|
||||
{
|
||||
Guid g;
|
||||
list.Add(Guid.TryParse(value.ToString(), out g) ? (object)g : elementType.GetDefaultValue());
|
||||
}
|
||||
if (Guid.TryParse(value.ToString(), out g))
|
||||
list.Add(elementType == typeof(Guid) ? (object)g : new Guid?(g));
|
||||
else
|
||||
list.Add(elementType.CastObject(value));
|
||||
list.Add(elementType.GetDefaultValue());
|
||||
}
|
||||
else if (targetElementType.IsEnum)
|
||||
list.Add(Enum.ToObject(targetElementType, value));
|
||||
else
|
||||
list.Add(targetElementType == elementType ? elementType.CastObject(value) : targetElementType.CastObject(value));
|
||||
}
|
||||
if (propertyType.IsArray)
|
||||
{
|
||||
@@ -14834,12 +14877,7 @@ namespace DynamORM
|
||||
{
|
||||
if (attr == null || string.IsNullOrEmpty(attr.ColumnName))
|
||||
return 0;
|
||||
|
||||
int ordinal = reader.GetOrdinal(attr.ColumnName);
|
||||
if (ordinal < 0)
|
||||
throw new IndexOutOfRangeException(attr.ColumnName);
|
||||
|
||||
return ordinal;
|
||||
return reader.GetOrdinal(attr.ColumnName);
|
||||
}
|
||||
}
|
||||
/// <summary>Framework detection and specific implementations.</summary>
|
||||
@@ -17886,7 +17924,7 @@ namespace DynamORM
|
||||
}
|
||||
}
|
||||
/// <summary>Declares mapping of a typed procedure result property to a specific result set.</summary>
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
|
||||
public class ProcedureResultAttribute : Attribute
|
||||
{
|
||||
/// <summary>Initializes a new instance of the <see cref="ProcedureResultAttribute"/> class.</summary>
|
||||
|
||||
@@ -101,6 +101,24 @@ namespace DynamORM.Tests.Helpers
|
||||
public int Status { get; set; }
|
||||
}
|
||||
|
||||
public class ProcedureAttributedFieldResult
|
||||
{
|
||||
[ProcedureResult(0)]
|
||||
public string FirstCode;
|
||||
|
||||
[ProcedureResult(1)]
|
||||
public System.Collections.Generic.List<string> Codes;
|
||||
|
||||
[ProcedureResult(2, ColumnName = "State")]
|
||||
public System.Collections.Generic.IEnumerable<int> States;
|
||||
|
||||
[ProcedureResult(3)]
|
||||
public Users User;
|
||||
|
||||
[ProcedureResult(4, Name = "users_table")]
|
||||
public DataTable UsersTable;
|
||||
}
|
||||
|
||||
public class ProcedureMultiResultArgs : IProcedureParameters<ProcedureMultiResult>
|
||||
{
|
||||
[ProcedureParameter("status", Direction = ParameterDirection.Output, Order = 1, DbType = DbType.Int32)]
|
||||
|
||||
@@ -206,6 +206,36 @@ namespace DynamORM.Tests.Procedure
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestDeclaredResultCanReadAttributedFieldResultSets()
|
||||
{
|
||||
using (var reader = new FakeMultiResultDataReader(
|
||||
Tuple.Create(new[] { "Code" }, new[] { typeof(string) }, new[] { new object[] { "FIELD-FIRST" }, new object[] { "FIELD-SECOND" } }),
|
||||
Tuple.Create(new[] { "Code" }, new[] { typeof(string) }, new[] { new object[] { "C" }, new object[] { "D" } }),
|
||||
Tuple.Create(new[] { "State" }, new[] { typeof(int) }, new[] { new object[] { 30 }, new object[] { 40 } }),
|
||||
Tuple.Create(
|
||||
new[] { "id", "code", "first" },
|
||||
new[] { typeof(long), typeof(string), typeof(string) },
|
||||
new[] { new object[] { 4L, "U4", "Four" } }),
|
||||
Tuple.Create(
|
||||
new[] { "id", "code", "first" },
|
||||
new[] { typeof(long), typeof(string), typeof(string) },
|
||||
new[] { new object[] { 5L, "U5", "Five" }, new object[] { 6L, "U6", "Six" } })))
|
||||
{
|
||||
var result = DynamicProcedureResultBinder.ReadDeclaredResult(typeof(ProcedureAttributedFieldResult), reader) as ProcedureAttributedFieldResult;
|
||||
|
||||
Assert.NotNull(result);
|
||||
Assert.AreEqual("FIELD-FIRST", result.FirstCode);
|
||||
CollectionAssert.AreEqual(new[] { "C", "D" }, result.Codes);
|
||||
CollectionAssert.AreEqual(new[] { 30, 40 }, result.States);
|
||||
Assert.NotNull(result.User);
|
||||
Assert.AreEqual(4L, result.User.Id);
|
||||
Assert.NotNull(result.UsersTable);
|
||||
Assert.AreEqual("users_table", result.UsersTable.TableName);
|
||||
Assert.AreEqual(2, result.UsersTable.Rows.Count);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestDeclaredResultPayloadCanAugmentReaderResult()
|
||||
{
|
||||
@@ -233,9 +263,10 @@ namespace DynamORM.Tests.Procedure
|
||||
[Test]
|
||||
public void TestDeclaredResultBindingDetectionSupportsAttributedResults()
|
||||
{
|
||||
Assert.IsTrue(DynamicProcedureResultBinder.HasDeclaredResultBinding(typeof(ProcedureMultiResult)));
|
||||
Assert.IsTrue(DynamicProcedureResultBinder.HasDeclaredResultBinding(typeof(ProcedureAttributedResult)));
|
||||
Assert.IsFalse(DynamicProcedureResultBinder.HasDeclaredResultBinding(typeof(ProcedureParameterResult)));
|
||||
Assert.IsTrue(DynamicProcedureResultBinder.CanReadResults(typeof(ProcedureMultiResult)));
|
||||
Assert.IsTrue(DynamicProcedureResultBinder.CanReadResults(typeof(ProcedureAttributedResult)));
|
||||
Assert.IsTrue(DynamicProcedureResultBinder.CanReadResults(typeof(ProcedureAttributedFieldResult)));
|
||||
Assert.IsFalse(DynamicProcedureResultBinder.CanReadResults(typeof(ProcedureParameterResult)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,7 +282,7 @@ namespace DynamORM
|
||||
|
||||
object mainResult = null;
|
||||
|
||||
if (types.Count == 0 && DynamicProcedureResultBinder.HasDeclaredResultBinding(declaredResultType))
|
||||
if (types.Count == 0 && DynamicProcedureResultBinder.CanReadResults(declaredResultType))
|
||||
{
|
||||
using (IDataReader rdr = cmd.ExecuteReader())
|
||||
using (IDataReader cache = rdr.CachedReader())
|
||||
|
||||
@@ -38,10 +38,26 @@ namespace DynamORM.Helpers
|
||||
{
|
||||
internal static class DynamicProcedureResultBinder
|
||||
{
|
||||
private sealed class ResultPropertyBinding
|
||||
private sealed class ResultMemberBinding
|
||||
{
|
||||
public ProcedureResultAttribute Attribute { get; set; }
|
||||
public PropertyInfo Property { get; set; }
|
||||
public MemberInfo Member { get; set; }
|
||||
public Type MemberType { get; set; }
|
||||
public int SortOrder { get; set; }
|
||||
|
||||
public void SetValue(object instance, object value)
|
||||
{
|
||||
PropertyInfo property = Member as PropertyInfo;
|
||||
if (property != null)
|
||||
{
|
||||
property.SetValue(instance, value, null);
|
||||
return;
|
||||
}
|
||||
|
||||
FieldInfo field = Member as FieldInfo;
|
||||
if (field != null)
|
||||
field.SetValue(instance, value);
|
||||
}
|
||||
}
|
||||
|
||||
internal static bool IsProcedureContract(object item)
|
||||
@@ -60,10 +76,15 @@ namespace DynamORM.Helpers
|
||||
return iface == null ? null : iface.GetGenericArguments()[0];
|
||||
}
|
||||
|
||||
internal static bool HasDeclaredResultBinding(Type resultType)
|
||||
internal static bool CanReadResults(Type resultType)
|
||||
{
|
||||
return resultType != null &&
|
||||
(typeof(IProcedureResultReader).IsAssignableFrom(resultType) || GetResultPropertyBindings(resultType).Count > 0);
|
||||
(typeof(IProcedureResultReader).IsAssignableFrom(resultType) || GetResultMemberBindings(resultType).Count > 0);
|
||||
}
|
||||
|
||||
internal static bool HasDeclaredResultBinding(Type resultType)
|
||||
{
|
||||
return CanReadResults(resultType);
|
||||
}
|
||||
|
||||
internal static object CreateDeclaredResult(Type resultType)
|
||||
@@ -80,14 +101,14 @@ namespace DynamORM.Helpers
|
||||
|
||||
internal static object ReadDeclaredResult(Type resultType, IDataReader reader)
|
||||
{
|
||||
if (!HasDeclaredResultBinding(resultType))
|
||||
if (!CanReadResults(resultType))
|
||||
throw new InvalidOperationException(string.Format("Type '{0}' does not declare a supported procedure result binding.", resultType == null ? "<null>" : resultType.FullName));
|
||||
|
||||
object instance = CreateDeclaredResult(resultType);
|
||||
|
||||
IList<ResultPropertyBinding> bindings = GetResultPropertyBindings(resultType);
|
||||
IList<ResultMemberBinding> bindings = GetResultMemberBindings(resultType);
|
||||
if (bindings.Count > 0)
|
||||
BindResultProperties(instance, reader, bindings);
|
||||
BindResultMembers(instance, reader, bindings);
|
||||
else
|
||||
((IProcedureResultReader)instance).ReadResults(reader);
|
||||
|
||||
@@ -118,22 +139,36 @@ namespace DynamORM.Helpers
|
||||
return payload.ToDynamic();
|
||||
}
|
||||
|
||||
private static IList<ResultPropertyBinding> GetResultPropertyBindings(Type resultType)
|
||||
private static IList<ResultMemberBinding> GetResultMemberBindings(Type resultType)
|
||||
{
|
||||
return resultType.GetProperties(BindingFlags.Instance | BindingFlags.Public)
|
||||
var properties = resultType.GetProperties(BindingFlags.Instance | BindingFlags.Public)
|
||||
.Where(x => x.CanWrite && x.GetIndexParameters().Length == 0)
|
||||
.Select(x => new ResultPropertyBinding
|
||||
.Select(x => new ResultMemberBinding
|
||||
{
|
||||
Property = x,
|
||||
Member = x,
|
||||
MemberType = x.PropertyType,
|
||||
SortOrder = x.MetadataToken,
|
||||
Attribute = x.GetCustomAttributes(typeof(ProcedureResultAttribute), true).Cast<ProcedureResultAttribute>().FirstOrDefault()
|
||||
})
|
||||
});
|
||||
|
||||
var fields = resultType.GetFields(BindingFlags.Instance | BindingFlags.Public)
|
||||
.Where(x => !x.IsInitOnly && !x.IsLiteral)
|
||||
.Select(x => new ResultMemberBinding
|
||||
{
|
||||
Member = x,
|
||||
MemberType = x.FieldType,
|
||||
SortOrder = x.MetadataToken,
|
||||
Attribute = x.GetCustomAttributes(typeof(ProcedureResultAttribute), true).Cast<ProcedureResultAttribute>().FirstOrDefault()
|
||||
});
|
||||
|
||||
return properties.Concat(fields)
|
||||
.Where(x => x.Attribute != null)
|
||||
.OrderBy(x => x.Attribute.ResultIndex)
|
||||
.ThenBy(x => x.Property.MetadataToken)
|
||||
.ThenBy(x => x.SortOrder)
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private static void BindResultProperties(object instance, IDataReader reader, IList<ResultPropertyBinding> bindings)
|
||||
private static void BindResultMembers(object instance, IDataReader reader, IList<ResultMemberBinding> bindings)
|
||||
{
|
||||
ValidateBindings(instance.GetType(), bindings);
|
||||
|
||||
@@ -142,7 +177,7 @@ namespace DynamORM.Helpers
|
||||
|
||||
for (int i = 0; i < bindings.Count; i++)
|
||||
{
|
||||
ResultPropertyBinding binding = bindings[i];
|
||||
ResultMemberBinding binding = bindings[i];
|
||||
while (hasCurrent && currentIndex < binding.Attribute.ResultIndex)
|
||||
{
|
||||
hasCurrent = reader.NextResult();
|
||||
@@ -152,8 +187,8 @@ namespace DynamORM.Helpers
|
||||
if (!hasCurrent || currentIndex != binding.Attribute.ResultIndex)
|
||||
break;
|
||||
|
||||
object value = ReadResultValue(binding.Property.PropertyType, binding.Attribute, reader);
|
||||
binding.Property.SetValue(instance, value, null);
|
||||
object value = ReadResultValue(binding.MemberType, binding.Attribute, reader);
|
||||
binding.SetValue(instance, value);
|
||||
|
||||
if (i + 1 < bindings.Count)
|
||||
{
|
||||
@@ -163,7 +198,7 @@ namespace DynamORM.Helpers
|
||||
}
|
||||
}
|
||||
|
||||
private static void ValidateBindings(Type resultType, IList<ResultPropertyBinding> bindings)
|
||||
private static void ValidateBindings(Type resultType, IList<ResultMemberBinding> bindings)
|
||||
{
|
||||
var duplicates = bindings.GroupBy(x => x.Attribute.ResultIndex).FirstOrDefault(x => x.Count() > 1);
|
||||
if (duplicates != null)
|
||||
@@ -196,6 +231,7 @@ namespace DynamORM.Helpers
|
||||
|
||||
private static object ReadSimpleValue(Type propertyType, ProcedureResultAttribute attr, IDataReader reader)
|
||||
{
|
||||
Type targetType = Nullable.GetUnderlyingType(propertyType) ?? propertyType;
|
||||
object value = null;
|
||||
int ordinal = -1;
|
||||
bool haveRow = false;
|
||||
@@ -213,19 +249,23 @@ namespace DynamORM.Helpers
|
||||
if (!haveRow || value == null)
|
||||
return propertyType.GetDefaultValue();
|
||||
|
||||
if (propertyType == typeof(Guid))
|
||||
if (targetType == typeof(Guid))
|
||||
{
|
||||
Guid g;
|
||||
if (Guid.TryParse(value.ToString(), out g))
|
||||
return g;
|
||||
return propertyType == typeof(Guid) ? (object)g : new Guid?(g);
|
||||
return propertyType.GetDefaultValue();
|
||||
}
|
||||
|
||||
return propertyType.CastObject(value);
|
||||
if (targetType.IsEnum)
|
||||
return Enum.ToObject(targetType, value);
|
||||
|
||||
return targetType == propertyType ? propertyType.CastObject(value) : targetType.CastObject(value);
|
||||
}
|
||||
|
||||
private static object ReadSimpleList(Type propertyType, Type elementType, ProcedureResultAttribute attr, IDataReader reader)
|
||||
{
|
||||
Type targetElementType = Nullable.GetUnderlyingType(elementType) ?? elementType;
|
||||
Type listType = typeof(List<>).MakeGenericType(elementType);
|
||||
var list = (System.Collections.IList)Activator.CreateInstance(listType);
|
||||
int ordinal = -1;
|
||||
@@ -246,13 +286,18 @@ namespace DynamORM.Helpers
|
||||
}
|
||||
|
||||
object value = reader[ordinal];
|
||||
if (elementType == typeof(Guid))
|
||||
if (targetElementType == typeof(Guid))
|
||||
{
|
||||
Guid g;
|
||||
list.Add(Guid.TryParse(value.ToString(), out g) ? (object)g : elementType.GetDefaultValue());
|
||||
}
|
||||
if (Guid.TryParse(value.ToString(), out g))
|
||||
list.Add(elementType == typeof(Guid) ? (object)g : new Guid?(g));
|
||||
else
|
||||
list.Add(elementType.CastObject(value));
|
||||
list.Add(elementType.GetDefaultValue());
|
||||
}
|
||||
else if (targetElementType.IsEnum)
|
||||
list.Add(Enum.ToObject(targetElementType, value));
|
||||
else
|
||||
list.Add(targetElementType == elementType ? elementType.CastObject(value) : targetElementType.CastObject(value));
|
||||
}
|
||||
|
||||
if (propertyType.IsArray)
|
||||
@@ -337,12 +382,7 @@ namespace DynamORM.Helpers
|
||||
{
|
||||
if (attr == null || string.IsNullOrEmpty(attr.ColumnName))
|
||||
return 0;
|
||||
|
||||
int ordinal = reader.GetOrdinal(attr.ColumnName);
|
||||
if (ordinal < 0)
|
||||
throw new IndexOutOfRangeException(attr.ColumnName);
|
||||
|
||||
return ordinal;
|
||||
return reader.GetOrdinal(attr.ColumnName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ using System;
|
||||
namespace DynamORM.Mapper
|
||||
{
|
||||
/// <summary>Declares mapping of a typed procedure result property to a specific result set.</summary>
|
||||
[AttributeUsage(AttributeTargets.Property)]
|
||||
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
|
||||
public class ProcedureResultAttribute : Attribute
|
||||
{
|
||||
/// <summary>Initializes a new instance of the <see cref="ProcedureResultAttribute"/> class.</summary>
|
||||
|
||||
Reference in New Issue
Block a user