Я начал изучать AutoMapper и у меня есть сценарий «управляемый данными» ... У меня есть код для заполнения свойств сущностей из SqlDataReader на основе некоторой «информации о схеме», которую я передаю ...
Далее я хочу взять свойства Entity ... и затем, основываясь на имеющейся у меня информации Schema, создать набор SqlParameters из значений объекта ...
Идеальная работа для AutoMapper ... но я вижумного сглаживания от графа объектов к графу объектов, но нет простых примеров для этой задачи ... При рассмотрении этого я немного наткнулся на некоторые нюансы, но у меня есть приблизительное представление о том, что я должен делать ...
Я набросал следующее ... Я пытаюсь использовать TypeConverters и регистрирую их заранее, но когда я выполняю фактическую операцию map.ForMember (), она выдает ошибку с жалобой
«Настраиваемая конфигурация для элементов поддерживается только для отдельных элементов верхнего уровня для типа.»
Несколько вариантов, которые я пробовал и не увенчался успехом...
(1) пробовал гораздо более простые версии ... (2) пытался использовать механизм ConstructUsing (), и тогда целью операции на самом деле является свойство SqlParameter. [[[Value]]] (большинствоскорее всего, «правильный» путь в правильном мышлении AutoMapper ??) (3) пытался предварительно создать список целей и затем «найти» соответствующий параметр - но установка значения .Value все еще оставалась недостающей частью этого уравнения..
Будучи новичком в AutoMapper, я ожидал несколько проблем, но потратил достаточно времени на это и не нашел ничего очевидного ... кажется, что это должен быть простой вариант использования для фреймворка ... Iдолжно быть пропущено что-то очевидное ...
class Program
{
static void Main(string[] args)
{
// Drive it by some data... Say some mapping info we have from elsewhere...
var myMappingPairs = new List<MyMappingInfo>()
{
new MyMappingInfo() { PropertyName = "MyGuidProperty", ParameterName = "Param00" },
new MyMappingInfo() { PropertyName = "MyStringProperty", ParameterName = "Param01" },
new MyMappingInfo() { PropertyName = "MyInt16Property", ParameterName = "Param02" },
new MyMappingInfo() { PropertyName = "MyInt32Property", ParameterName = "Param03" },
new MyMappingInfo() { PropertyName = "MyInt64Property", ParameterName = "Param04" }
};
// We can try to register these, but the sytax isn't clear to me yet...
Mapper.CreateMap<Guid, SqlParameter>().ConvertUsing<GuidToSqlParameterConverter>();
Mapper.CreateMap<String, SqlParameter>().ConvertUsing<StringToSqlParameterConverter>();
Mapper.CreateMap<Int16, SqlParameter>().ConvertUsing<Int16ToSqlParameterConverter>();
Mapper.CreateMap<Int32, SqlParameter>().ConvertUsing<Int32ToSqlParameterConverter>();
Mapper.CreateMap<Int64, SqlParameter>().ConvertUsing<Int64ToSqlParameterConverter>();
// Next we'll build our mapping from the "pairings"...
var map = Mapper.CreateMap<MySourceEntity, List<SqlParameter>>();
foreach (var mappingPair in myMappingPairs)
{
map.ForMember
(
destination => destination,
options => options.ResolveUsing<PropertyNameResolver>().FromMember
(
mappingPair.PropertyName // <-- Data Driven Property Name...
)
);
}
// Create a test entity...
var entity = new MySourceEntity()
{
MyGuidProperty = Guid.NewGuid(),
MyStringProperty = "Hello AutoMapper",
MyInt16Property = Int16.MaxValue,
MyInt32Property = Int32.MaxValue,
MyInt64Property = Int64.MaxValue
};
// Map it...
var values = Mapper.Map<MySourceEntity, object[]>
(
entity
);
}
}
public class MySourceEntity
{
public string MyStringProperty { get; set; }
public DateTime? MyDateTimeProperty { get; set; }
public Byte? MyByteProperty { get; set; }
public Int16? MyInt16Property { get; set; }
public Int32? MyInt32Property { get; set; }
public Int64? MyInt64Property { get; set; }
public Guid? MyGuidProperty { get; set; }
public List<String> ThisShouldntGetMapped { get; set; }
public StringBuilder NorShouldThis { get; set; }
}
public class MyMappingInfo
{
public String PropertyName { get; set; }
public String ParameterName { get; set; }
public SqlDbType SqlDbType { get; set; }
}
public class GuidToSqlParameterConverter : AutoMapper.ITypeConverter<Guid, SqlParameter>
{
public SqlParameter Convert(ResolutionContext context)
{
if (context.IsSourceValueNull)
{
return new SqlParameter()
{
ParameterName = "GuidParam",
SqlDbType = SqlDbType.UniqueIdentifier,
Value = DBNull.Value
};
}
else
{
return new SqlParameter()
{
ParameterName = "GuidParam",
SqlDbType = SqlDbType.UniqueIdentifier,
Value = context.SourceValue
};
}
}
}
public class StringToSqlParameterConverter : AutoMapper.ITypeConverter<string, SqlParameter>
{
public SqlParameter Convert(ResolutionContext context)
{
if (context.IsSourceValueNull)
{
return new SqlParameter()
{
ParameterName = "StringParam",
SqlDbType = SqlDbType.NVarChar,
Value = DBNull.Value
};
}
else
{
return new SqlParameter()
{
ParameterName = "StringParam",
SqlDbType = SqlDbType.NVarChar,
Value = context.SourceValue
};
}
}
}
public class Int16ToSqlParameterConverter : AutoMapper.ITypeConverter<Int16, SqlParameter>
{
public SqlParameter Convert(ResolutionContext context)
{
if (context.IsSourceValueNull)
{
return new SqlParameter()
{
ParameterName = "Int16Param",
SqlDbType = SqlDbType.SmallInt,
Value = DBNull.Value
};
}
else
{
return new SqlParameter()
{
ParameterName = "Int16Param",
SqlDbType = SqlDbType.SmallInt,
Value = context.SourceValue
};
}
}
}
public class Int32ToSqlParameterConverter : AutoMapper.ITypeConverter<Int32, SqlParameter>
{
public SqlParameter Convert(ResolutionContext context)
{
if (context.IsSourceValueNull)
{
return new SqlParameter()
{
ParameterName = "Int32Param",
SqlDbType = SqlDbType.Int,
Value = DBNull.Value
};
}
else
{
return new SqlParameter()
{
ParameterName = "Int32Param",
SqlDbType = SqlDbType.Int,
Value = context.SourceValue
};
}
}
}
public class Int64ToSqlParameterConverter : AutoMapper.ITypeConverter<Int64, SqlParameter>
{
public SqlParameter Convert(ResolutionContext context)
{
if (context.IsSourceValueNull)
{
return new SqlParameter()
{
ParameterName = "Int64Param",
SqlDbType = SqlDbType.BigInt,
Value = DBNull.Value
};
}
else
{
return new SqlParameter()
{
ParameterName = "Int64Param",
SqlDbType = SqlDbType.BigInt,
Value = context.SourceValue
};
}
}
}
}
Я хотел бы знать, будет ли полученный в результате код выполнения в AutoMapper работать лучше, чем, скажем:
static IDictionary<string, object> GetDictionaryFromObject(object obj)
{
if (obj == null) return new Dictionary<string, object>();
return obj.GetType().GetProperties()
.ToDictionary(p => p.Name,
p => p.GetValue(obj, null) ?? DBNull.Value);
}
В этом и заключается весь смысл использования AutoMapper для меня ... Я уже знал, как писать код отражения ... и я всегда мог взглянуть на библиотеку, основанную исключительно на отражениях, чтобы получить дополнительную производительностьвыигрывает, но я думал, что AutoMapper, скорее всего, будет двумя птицами - одна сделка с камнем ...