返回總目錄html
有時,須要徹底控制一個類型到另外一個類型的轉換。一個類型一點都不像另外一個類型,並且轉換函數已經存在了,在這種狀況下,你想要從一個「寬鬆」的類型轉換成一個更強壯的類型,例如一個string的源類型到一個int32的目標類型。app
這裏有兩個類Source和Destination,要把前者映射到後者,代碼以下:函數
public class Source { public string Value1 { get; set; } public string Value2 { get; set; } public string Value3 { get; set; } }
public class Destination { public int Value1 { get; set; } public DateTime Value2 { get; set; } public Type Value3 { get; set; } }
截至發稿前,官方文檔這樣描述的「由於AutoMapper不清楚從string到int,Datetime或Type的映射,若是要嘗試映射的話,AutoMapper就會拋出異常(在映射時和配置檢查時)」。爲了建立 這些類型的映射,咱們必須提供自定義的類型轉換器,咱們有三種方法這樣作:測試
void ConvertUsing(Func<TSource, TDestination> mappingFunction); void ConvertUsing(ITypeConverter<TSource, TDestination> converter); void ConvertUsing<TTypeConverter>() where TTypeConverter : ITypeConverter<TSource, TDestination>;
可是,我先不實現自定義的類型轉換器試一下:spa
namespace ThirdAutoMapper { class Program { static void Main(string[] args) { Mapper.CreateMap<Source, Destination>(); var source = new Source { Value1 = "5", Value2 = "05/11/2015", Value3 = "ThirdAutoMapper.Source" }; var destination = Mapper.Map<Destination>(source); Console.WriteLine("destination.Value1={0}", destination.Value1); Console.WriteLine("destination.Value2={0}", destination.Value2); Console.Read(); } } }
出現以下錯誤,但從錯誤看來,只有從string到Type類型映射時,出現了錯誤,其餘兩種類型呢?code
如今咱們將源類型和目標類型的第三個屬性Value3註釋掉,同時註釋掉參與映射前的源類型對象的Value3屬性,再來試一下。htm
果真,發現映射成功。也就說說最新版的AutoMapper默承認以將string類型映射爲int和DateTime類型了。可是string仍是沒辦法映射爲Type類型。對象
對於以上AutoMapper的API給出的三種轉換方法,第一個選擇只是輸入一個源返回一個目標的函數,這對於簡單場合是有效的,可是對於更大的案例會變得難以處理。在更復雜的狀況下,咱們能夠一個自定義的類型轉換器,經過實現ITypeConverter<TSource, TDestination>接口建立:blog
第一種方法:接口
public class CustomTypeConverter : ITypeConverter<Source, Destination> { public Destination Convert(ResolutionContext context) { Source src = context.SourceValue as Source; var dest = new Destination { Value1 = System.Convert.ToInt32(src.Value1), Value2 = System.Convert.ToDateTime(src.Value2), Value3 = context.SourceType }; return dest; } }
而後給AutoMapper提供一個自定義類型的轉換器或者AutoMapper在運行時能實例化的簡化類型。對於上面的源/目標類型的映射配置就得以實現了:
修改Main方法中的代碼爲:
static void Main(string[] args) { Mapper.CreateMap<Source, Destination>().ConvertUsing<CustomTypeConverter>(); var source = new Source { Value1 = "5", Value2 = "05/11/2015", Value3 = typeof(Source).ToString()
}; var destination = Mapper.Map<Destination>(source); Console.WriteLine("destination.Value1={0}", destination.Value1); Console.WriteLine("destination.Value2={0}", destination.Value2); Console.WriteLine(destination.Value3.ToString()==source.Value3); Console.WriteLine(destination.Value3); Console.Read(); }
測試結果以下,映射成功!
第二種方法:
每一個類型分別實現ITypeConverter接口:
public class DateTimeTypeConverter:ITypeConverter<string,DateTime> { public DateTime Convert(ResolutionContext context) { return System.Convert.ToDateTime(context.SourceValue); } } public class TypeTypeConverter : ITypeConverter<string, Type> { public Type Convert(ResolutionContext context) { return context.SourceValue == typeof(Source).ToString() ? typeof(Source) : typeof(Destination); } }
static void Main(string[] args) { //我看網上不少這種寫法,包括官方文檔,可是我這樣寫編譯錯誤,多是如今的AutoMapper不支持了吧 // Mapper.CreateMap<string, int>().ConvertUsing( Convert.ToInt32); Mapper.CreateMap<string, int>().ConvertUsing((context, intNum) => Convert.ToInt32(context.SourceValue)); Mapper.CreateMap<string, DateTime>().ConvertUsing(new DateTimeTypeConverter().Convert); Mapper.CreateMap<string, Type>().ConvertUsing<TypeTypeConverter>(); Mapper.CreateMap<Source, Destination>(); //Mapper.CreateMap<Source, Destination>().ConvertUsing<CustomTypeConverter>(); var source = new Source { Value1 = "5", Value2 = "05/11/2015", Value3 = typeof(Source).ToString() }; var destination = Mapper.Map<Destination>(source); Console.WriteLine("destination.Value1={0}", destination.Value1); Console.WriteLine("destination.Value2={0}", destination.Value2); Console.WriteLine(destination.Value3.ToString()==source.Value3); Console.WriteLine(destination.Value3); Console.Read(); }
測試結果,一樣完美經過。
目前實如今AutoMapper中,已經修改了ITypeConverter接口中的Convert方法,所以從新寫了方法一和方法二的實現
方法一:
1
2
3
4
5
6
7
8
9
10
11
|
public
class
CustomTypeConverter : ITypeConverter<Source, Destination>
{
public
Destination Convert(Source source, Destination destination, ResolutionContext context)
{
destination =
new
Destination();
destination.Value1 = System.Convert.ToInt32(source.Value1);
destination.Value2 = System.Convert.ToDateTime(source.Value2);
destination.Value3 = source.GetType();
return
destination;
}
}
|
方法二:
1
2
3
4
5
6
7
|
public
class
TypeConverter : ITypeConverter<
string
, Type>
{
public
Type Convert(
string
source, Type destination, ResolutionContext context)
{
return
Type.GetType(source);
}
}
|