2

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;

どこが間違っているのか教えてください

4

0 に答える 0