-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
create overload Query<T> to customize the mapper #360
Comments
There are multiple ways to achieve it, we do not need this modification ideally:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace Dapper
{
/// <summary>
/// Uses the Name value of the <see cref="ColumnAttribute"/> specified to determine
/// the association between the name of the column in the query results and the member to
/// which it will be extracted. If no column mapping is present all members are mapped as
/// usual.
/// </summary>
/// <typeparam name="T">The type of the object that this association between the mapper applies to.</typeparam>
public class ColumnAttributeTypeMapper<T> : FallbackTypeMapper
{
public ColumnAttributeTypeMapper()
: base(new SqlMapper.ITypeMap[]
{
new CustomPropertyTypeMap(
typeof(T),
(type, columnName) =>
type.GetProperties().FirstOrDefault(prop =>
prop.GetCustomAttributes(false)
.OfType<ColumnAttribute>()
.Any(attr => attr.Name == columnName)
)
),
new DefaultTypeMap(typeof(T))
})
{
}
}
/// <summary>
///
/// </summary>
[AttributeUsage(AttributeTargets.Property, AllowMultiple = true)]
public class ColumnAttribute : Attribute
{
public string Name { get; set; }
}
/// <summary>
///
/// </summary>
public class FallbackTypeMapper : SqlMapper.ITypeMap
{
private readonly IEnumerable<SqlMapper.ITypeMap> _mappers;
public FallbackTypeMapper(IEnumerable<SqlMapper.ITypeMap> mappers)
{
_mappers = mappers;
}
public ConstructorInfo FindConstructor(string[] names, Type[] types)
{
foreach (var mapper in _mappers)
{
try
{
ConstructorInfo result = mapper.FindConstructor(names, types);
if (result != null)
{
return result;
}
}
catch (NotImplementedException)
{
}
}
return null;
}
public SqlMapper.IMemberMap GetConstructorParameter(ConstructorInfo constructor, string columnName)
{
foreach (var mapper in _mappers)
{
try
{
var result = mapper.GetConstructorParameter(constructor, columnName);
if (result != null)
{
return result;
}
}
catch (NotImplementedException)
{
}
}
return null;
}
public SqlMapper.IMemberMap GetMember(string columnName)
{
foreach (var mapper in _mappers)
{
try
{
var result = mapper.GetMember(columnName);
if (result != null)
{
return result;
}
}
catch (NotImplementedException)
{
}
}
return null;
}
public ConstructorInfo FindExplicitConstructor()
{
return _mappers
.Select(mapper => mapper.FindExplicitConstructor())
.FirstOrDefault(result => result != null);
}
}
} |
@mrinalkamboj tip on the issues: use code fences to get awesome highlighting, check out your updated comment to see my update, like this:
|
@NickCraver Thanks, will be careful from next time onward |
In my case i want to map multiple fields into a single dictionary, so for each a record i just want to execute an action to modify the result object.. |
@mdissel IMO that has to be a custom code, not sure if it would be feasible to provide the same Out of box, though @NickCraver can suggest better |
See the proposal above about extending the mapper, this would allow you to change the mapping for the type in a central place, hopefully covering this use case as well. |
I'm going to close this one out because I don't think such an API will happen in this form. Mainly because Query is simply the wrong place, and we cache the deserializer where this is affected. It'd be much better to plug in where the deserializer generation happens - we'll work on opening up the TypeMapper a bit more. |
Add a new overload to Query with an optional parameter Func<IDataRecord, T, T> map
In this function the caller can modify the default mapping with access to the IDataRecord and the result object T
Something like this:
The text was updated successfully, but these errors were encountered: