在.NET开发中,对象映射是一个常见的需求,它允许开发者将一个对象的属性或字段映射到另一个对象。TinyMapper是一个轻量级的.NET对象映射器,其主要优势在于性能。本文将介绍如何使用TinyMapper进行对象映射,并对其性能进行分析。
TinyMapper允许开发者轻松地将一个对象映射到另一个对象。例如,可以将Person类的对象映射到PersonDto类的对象。以下是使用TinyMapper进行映射的示例代码:
private static void MapPerson()
{
TinyMapper.Bind<Person, PersonDto>();
var person = new Person
{
Id = Guid.NewGuid(),
FirstName = "John",
LastName = "Doe",
Email = "support@tinymapper.net",
Address = "Wall Street",
CreateTime = DateTime.Now,
Nickname = "Object Mapper",
Phone = "Call Me Maybe "
};
var personDto = TinyMapper.Map<PersonDto>(person);
}
在上述代码中,首先绑定了Person类和PersonDto类之间的映射关系,然后创建了一个Person对象,并使用TinyMapper将其映射到PersonDto对象。
性能是TinyMapper的一个重要优势。为了验证这一点,使用Person类进行了性能测试,并将TinyMapper与AutoMapper进行了比较。测试代码如下:
private static void MeasureHandwritten()
{
Person person = CreatePerson();
Stopwatch stopwatch = Stopwatch.StartNew();
for (int i = 0; i < Iterations; i++)
{
PersonDto personDto = MapHandwritten(person);
}
stopwatch.Stop();
Console.WriteLine("Handwritten: {0}ms", stopwatch.Elapsed.TotalMilliseconds);
}
private static void MeasureTinyMapper()
{
Person person = CreatePerson();
TinyMapper.Bind<Person, PersonDto>();
Stopwatch stopwatch = Stopwatch.StartNew();
for (int i = 0; i < Iterations; i++)
{
var personDto = TinyMapper.Map<PersonDto>(person);
}
stopwatch.Stop();
Console.WriteLine("TinyMapper: {0}ms", stopwatch.Elapsed.TotalMilliseconds);
}
private static void MeasureAutoMapper()
{
Person person = CreatePerson();
Mapper.CreateMap<Person, PersonDto>();
Stopwatch stopwatch = Stopwatch.StartNew();
for (int i = 0; i < Iterations; i++)
{
var personDto = Mapper.Map<PersonDto>(person);
}
stopwatch.Stop();
Console.WriteLine("AutoMapper: {0}ms", stopwatch.Elapsed.TotalMilliseconds);
}
在测试中,创建了一个Person类实例,并将其所有属性映射到PersonDto类。重复测量了1,000,000次,以确保结果的准确性。
TinyMapper可以通过NuGet包管理器安装。首先,需要绑定源类型和目标类型,如下所示:
TinyMapper.Bind<Person, PersonDto>();
绑定后,TinyMapper就知道如何将Person对象映射到PersonDto对象。最后,调用Map方法,将得到映射后的对象。这是一个完整的示例:
var personDto = TinyMapper.Map<PersonDto>(person);
需要执行两个步骤:
注意:如果是在多线程应用程序中使用TinyMapper,请在应用程序启动时注册所有绑定。在应用程序运行时,只需要调用Map方法。这样,将获得速度和线程安全性。TinyMapper可以为完成第一步,即只需要调用Map方法,结果将是一样的。
注意:在没有调用Bind的情况下调用Map,这不是线程安全的。
让来看一个更复杂的示例。例如,有以下类:
public sealed class PersonComplex
{
public Address Address { get; set; }
public DateTime CreateTime { get; set; }
public IReadOnlyList<string> Emails { get; set; }
public string FirstName { get; set; }
public Guid Id { get; set; }
public string LastName { get; set; }
public string Nickname { get; set; }
}
public sealed class Address
{
public string Phone { get; set; }
public string Street { get; set; }
public string ZipCode { get; set; }
}
不想映射CreateTime和Nickname属性。如所见,刚刚将CreateTime和Nickname标记为忽略。绑定LastName从源Surname到目标类,并绑定IList的电子邮件到List。TinyMapper允许:
例如,有以下类:
public sealed class PersonCustomSource
{
public IList<string> Emails { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
public sealed class PersonCustomTarget
{
public IList<string> Emails { get; set; }
public string FullName { get; set; }
}
希望将FirstName和LastName映射到FullName,使用以下约定"FirstName LastName"。TinyMapper支持TypeConverter,即可以为任何类型创建自己的TypeConverter。
public sealed class PersonTypeConverter : TypeConverter
{
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
return destinationType == typeof(PersonCustomTarget);
}
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
var concreteValue = (PersonCustomSource)value;
var result = new PersonCustomTarget
{
FullName = string.Format("{0} {1}", concreteValue.FirstName, concreteValue.LastName),
Emails = new List<string>(concreteValue.Emails)
};
return result;
}
}
下一步是注册类型转换器。TypeConverter支持通过属性注册...
[TypeConverter(typeof(PersonTypeConverter))]
public sealed class PersonCustomSource
{
public IList<string> Emails { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
...或代码:
TypeDescriptor.AddAttributes(typeof(PersonCustomSource), new TypeConverterAttribute(typeof(PersonTypeConverter)));
这是一个额外的示例,展示了如何实现类型转换器。