自动映射:使用非匹配属性的属性进行映射

时间:2013-01-11 09:57:08

标签: automapper typeconverter

我有一个场景,我正在创建一个映射实用程序,通过它我们可以将DataReader映射到实体。

Mapper.CreateMap<IDataReader, T>();
List<T> tList = Mapper.Map<List<T>>(reader);
return tList;

如果实体具有与存储过程输出中相同的列,则此工作正常。但是,我正在研究一些列名不匹配的旧代码。所以我创建了一个属性,通过该属性我可以从sprocs中指定相应的列。我使用这样的代码指定它们

[DBColumn('EmployeeName')]
public string EmpName { get; set; }

有什么办法可以用泛型/反射来实现这个目的吗?请注意,我有多个这样的实例,我正在构建一个实用程序。所以我无法使用ForMember方法来实现这一目标。

更新:我尝试创建这样的自定义转换器。但是,我的转换函数根本没有被调用。

自定义转换器

public class CustomConverter<T> : ITypeConverter<System.Data.IDataReader, T>
{
    private ResolutionContext _Context = null;
    private Dictionary<string, string> _CustomProps { get; set; }
    public T Convert(ResolutionContext context)
    {
        _Context = context;

        if (_Context.SourceValue != null &&
            !(_Context.SourceValue is System.Data.IDataReader))
        {
            string message = "Value supplied is of type {0} but expected {1}.\n" +
                             "Change the type converter source type, or redirect " +
                             "the source value supplied to the value resolver using FromMember.";

            throw new AutoMapperMappingException(_Context, string.Format(
                message, typeof(System.Data.IDataReader), _Context.SourceValue.GetType()));
        }
        _CustomProps = new Dictionary<string, string>();
        foreach (PropertyInfo propInfo in context.DestinationType.GetProperties())
        {
            if (propInfo.CustomAttributes.Any(attr => attr.AttributeType == typeof(DBColumn)))
            {
                DBColumn propertyValue = (DBColumn)propInfo.GetCustomAttribute(typeof(DBColumn));
                _CustomProps.Add(propertyValue.ColumnName, propInfo.Name);
            }
        }
        //return base.Convert(context);            
        return ConvertCore((System.Data.IDataReader)context.SourceValue);
    }

    protected T ExistingDestination
    {
        get
        {
            if (_Context == null)
            {
                string message = "ResolutionContext is not yet set. " +
                                 "Only call this property inside the 'ConvertCore' method.";

                throw new InvalidOperationException(message);
            }

            if (_Context.DestinationValue != null &&
                !(_Context.DestinationValue is T))
            {
                string message = "Destination Value is of type {0} but expected {1}.";

                throw new AutoMapperMappingException(_Context, string.Format(
                    message, typeof(T), _Context.DestinationValue.GetType()));
            }

            return (T)_Context.DestinationValue;
        }
    }

    protected T ConvertCore(System.Data.IDataReader source)
    {
        T obj = ExistingDestination;
        if (obj != null)
        {
            foreach (KeyValuePair<string, string> keyValuePair in _CustomProps)
            {
                PropertyInfo prop = obj.GetType().GetProperty(keyValuePair.Key,  BindingFlags.Public | BindingFlags.Instance);
                if (null != prop && prop.CanWrite)
                {
                    prop.SetValue(obj, System.Convert.ChangeType(source[keyValuePair.Value], prop.PropertyType));
                }
            }
        }
        return obj;
    }

我指定在下面的语句中使用此CustomConverter。

        Mapper.CreateMap<IDataReader, T>().ConvertUsing<CustomConverter<T>>();
        List<T> tList = Mapper.Map<List<T>>(reader);
        return tList;

请告诉我,我出错的地方

0 个答案:

没有答案