C# 中的简单模型/实体映射器





5.00/5 (7投票s)
让我们看看如何使用反射在 C# 中创建一个简单的模型或实体映射器
引言
在 C# 中工作时,我们可能希望将一个模型/实体映射到另一个模型/实体。 反射是可以在此时帮助我们的关键。
所以让我们看看如何使用反射在 C# 中创建一个简单的模型或实体映射器。
背景
假设我们有一些模型,例如
IStudent 接口
interface IStudent
{
long Id { get; set; }
string Name { get; set; }
}
Student 类
class Student : IStudent
{
public long Id { get; set; }
public string Name { get; set; }
}
StudentLog 类
class StudentLog : IStudent
{
public long LogId { get; set; }
public long Id { get; set; }
public string Name { get; set; }
}
其中 Student
和 StudentLog
都具有一些公共属性(名称和类型相同)。
MapperUtility
这是我们将用于映射的实用工具类
TTarget MapTo<TSource, TTarget> (this TSource aSource, TTarget aTarget)
- 将 aSource
的属性映射到给定的 aTarget
,并返回 aTarget
TTarget CreateMapped<TSource, TTarget> (this TSource aSource)
- 将 aSource
的属性映射到类型为 TTarget
的新创建的对象,并返回它
映射将适用于 TSource
和 TTarget
的 name
和 type
相同的属性。
public static class MapperUtility
{
/*passing values to given object*/
public static TTarget MapTo<TSource, TTarget>(this TSource aSource, TTarget aTarget)
{
const BindingFlags flags = BindingFlags.Public |
BindingFlags.Instance | BindingFlags.NonPublic;
/*TODO: find fields*/
var srcFields = (from PropertyInfo aProp in typeof(TSource).GetProperties(flags)
where aProp.CanRead //check if prop is readable
select new
{
Name = aProp.Name,
Type = Nullable.GetUnderlyingType(aProp.PropertyType) ??
aProp.PropertyType
}).ToList();
var trgFields = (from PropertyInfo aProp in aTarget.GetType().GetProperties(flags)
where aProp.CanWrite //check if prop is writeable
select new
{
Name = aProp.Name,
Type = Nullable.GetUnderlyingType(aProp.PropertyType) ??
aProp.PropertyType
}).ToList();
/*TODO: common fields where name and type same*/
var commonFields = srcFields.Intersect(trgFields).ToList();
/*assign values*/
foreach (var aField in commonFields)
{
var value = aSource.GetType().GetProperty(aField.Name).GetValue(aSource, null);
PropertyInfo propertyInfos = aTarget.GetType().GetProperty(aField.Name);
propertyInfos.SetValue(aTarget, value, null);
}
return aTarget;
}
/*returns new object with mapping*/
public static TTarget CreateMapped<TSource, TTarget>(this TSource aSource) where TTarget : new()
{
return aSource.MapTo(new TTarget());
}
}
创建新的映射
将从类型为 Student
的对象源创建新的 StudentLog
映射对象
Student source = new Student() { Id = 1, Name = "Smith" };
/*get new object, which been mapped*/
StudentLog newMapped = source.CreateMapped<Student, StudentLog>();
映射到现有对象
将从类型为 Student
的目标映射到类型为 StudentLog
的现有 aSourceLog
/*map to existing object*/
StudentLog aSourceLog = new StudentLog();
Student target = new Student();
target.Id = 2;
target.Name = "Tom";
aSourceLog = target.MapTo(aSourceLog);
//or
target.MapTo(aSourceLog);
限制
- 我使用了框架 4。
- 此映射器仅适用于类。 如果您尝试使用
struct
,它将无法映射,或者如果您尝试使用List<Student>
,它将引发错误。 - 我只需要这么多,所以我创建了它,如果您需要做更多的事情,请查看 AutoMapper。
您可以在附件中找到 VS2010 的解决方案。