EmitMapper を使用するのは初めてです。オブジェクト ex: Customer のリストがあり、このリストを CustomerDTO の ienumerable にマップしたいのですが、どうすればよいですか? TNX
1930 次
2 に答える
2
リストがあり、それを DTO のリストに変換したい場合は簡単です。
var mapper = ObjectMapperManager.DefaultInstance.GetMapper<Customer, CustomerDTO>();
IEnumerable<CustomerDTO> dtos = listOfCustomer.Select(mapper.map);
問題は、リストが User や UserDTO などの別のオブジェクトにある場合です。
class User {
public List<Customer> Customers { get; set; }
}
class UserDTO {
public IEnumerable<CustomerDTO> Customers { get; set; }
}
EmitMapper は List から Enumerable への変換をサポートしていないようです。それをサポートする方法は次のとおりです。
var customerMapper = ObjectMapperManager
.DefaultInstance.GetMapper<Customer, CustomerDTO>();
var mapper = ObjectMapperManager.DefaultInstance
.GetMapper<User, UserDTO>(
new DefaultMapConfig()
.ConvertUsing<List<Customer>, IEnumerable<CustomerDTO>>(
a => a.Select(customerMapper.Map))
);
于 2012-09-05T09:54:34.573 に答える
0
これは、カスタム クラスを作成し、インターフェイス「ICustomConverterProvider」を実装し、ConvertGeneric を「DefaultMapConfig」に追加することで実行できます。
EmitMapper のソース コードを調べたところ、「ArraysConverterProvider」という名前のクラスが見つかりました。これは、ICollection から配列へのデフォルトの汎用コンバーターです。
IEnumerable コレクションで動作するように、このクラスのコードを調整します。
class GenericIEnumerableConverterProvider : ICustomConverterProvider
{
public CustomConverterDescriptor GetCustomConverterDescr(
Type from,
Type to,
MapConfigBaseImpl mappingConfig)
{
var tFromTypeArgs = DefaultCustomConverterProvider.GetGenericArguments(from);
var tToTypeArgs = DefaultCustomConverterProvider.GetGenericArguments(to);
if (tFromTypeArgs == null || tToTypeArgs == null || tFromTypeArgs.Length != 1 || tToTypeArgs.Length != 1)
{
return null;
}
var tFrom = tFromTypeArgs[0];
var tTo = tToTypeArgs[0];
if (tFrom == tTo && (tFrom.IsValueType || mappingConfig.GetRootMappingOperation(tFrom, tTo).ShallowCopy))
{
return new CustomConverterDescriptor
{
ConversionMethodName = "Convert",
ConverterImplementation = typeof(GenericIEnumerableConverter_OneTypes<>),
ConverterClassTypeArguments = new[] { tFrom }
};
}
return new CustomConverterDescriptor
{
ConversionMethodName = "Convert",
ConverterImplementation = typeof(GenericIEnumerableConverter_DifferentTypes<,>),
ConverterClassTypeArguments = new[] { tFrom, tTo }
};
}
}
class GenericIEnumerableConverter_DifferentTypes<TFrom, TTo> : ICustomConverter
{
private Func<TFrom, TTo> _converter;
public IEnumerable<TTo> Convert(IEnumerable<TFrom> from, object state)
{
if (from == null)
{
return null;
}
TTo[] result = new TTo[from.Count()];
int idx = 0;
foreach (var f in from)
{
result[idx++] = _converter(f);
}
return result;
}
public void Initialize(Type from, Type to, MapConfigBaseImpl mappingConfig)
{
var staticConverters = mappingConfig.GetStaticConvertersManager() ?? StaticConvertersManager.DefaultInstance;
var staticConverterMethod = staticConverters.GetStaticConverter(typeof(TFrom), typeof(TTo));
if (staticConverterMethod != null)
{
_converter = (Func<TFrom, TTo>)Delegate.CreateDelegate(
typeof(Func<TFrom, TTo>),
null,
staticConverterMethod
);
}
else
{
_subMapper = ObjectMapperManager.DefaultInstance.GetMapperImpl(typeof(TFrom), typeof(TTo), mappingConfig);
_converter = ConverterBySubmapper;
}
}
ObjectsMapperBaseImpl _subMapper;
private TTo ConverterBySubmapper(TFrom from)
{
return (TTo)_subMapper.Map(from);
}
}
class GenericIEnumerableConverter_OneTypes<T>
{
public IEnumerable<T> Convert(IEnumerable<T> from, object state)
{
if (from == null)
{
return null;
}
return from;
}
}
このコードは、可能な限り最小限の変更を加えた単なるコピーであり、多くの階層レベルを持つオブジェクトに適用できます。
上記のコードは、次のコマンドで使用できます。
new DefaultMapConfig().ConvertGeneric(
typeof(IEnumerable<>),
typeof(IEnumerable<>),
new GenericIEnumerableConverterProvider());
これは私の一日を救いました、そして私もあなたの日を救いたいです!へへへ
于 2016-10-24T14:11:14.963 に答える