AutoMapper(三)


返回總目錄


自定義類型轉換

有時,需要完全控制一個類型到另一個類型的轉換。一個類型一點都不像另一個類型,而且轉換函數已經存在了,在這種情況下,你想要從一個“寬松”的類型轉換成一個更強壯的類型,例如一個string的源類型到一個int32的目標類型。

這里有兩個類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>;

但是,我先不實現自定義的類型轉換器試一下:

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類型映射時,出現了錯誤,其他兩種類型呢?

image

現在我們將源類型和目標類型的第三個屬性Value3注釋掉,同時注釋掉參與映射前的源類型對象的Value3屬性,再來試一下。

image

果然,發現映射成功。也就說說最新版的AutoMapper默認可以將string類型映射為int和DateTime類型了。但是string還是沒辦法映射為Type類型。

對於以上AutoMapper的API給出的三種轉換方法,第一個選擇只是輸入一個源返回一個目標的函數,這對於簡單場合是有效的,但是對於更大的案例會變得難以處理。在更復雜的情況下,我們可以一個自定義的類型轉換器,通過實現ITypeConverter<TSource, TDestination>接口創建:

第一種方法:

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();
}

 

測試結果如下,映射成功!

image

第二種方法:

每個類型分別實現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();
}

測試結果,同樣完美通過。

image


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM