将实体转换为视图模型以与web api一起使用
本文关键字:api web 一起 转换 实体 视图 模型 | 更新日期: 2023-09-27 18:27:05
我目前正在努力寻找一种用Entitiy
对象填充ViewModel
对象的更好方法。我有以下Web Api
控制器方法:
[HttpGet]
public IEnumerable<ClientSearchViewModel> FindClients(string query)
{
var clients = _clientService.SearchClient(query).ToList();
var returnClients = new List<ClientSearchViewModel>();
foreach (var client in clients)
{
returnClients.Add(new ClientSearchViewModel(client));
}
return returnClients;
}
我在我的ClientSearchViewModel
构造函数中这样做
public ClientSearchViewModel(Client client)
{
this.Id = client.Id;
this.FirstName = client.PersonName.FirstName;
this.LastName = client.PersonName.LastName;
}
除了浏览返回对象的列表并创建新的ViewModel
列表之外,还有其他方法吗?
我强烈建议为此使用映射插件,例如:
AutoMapper
或
ValueInjector
像这样的插件将允许您在内部或数据层中使用的对象与外部对象(DTO/ViewModels)之间进行映射。它们可以处理许多开箱即用的事情,例如具有相同类型的任何类似命名属性的自动映射,但也允许在属性或类型的特定映射中进行大量控制,以备您需要更自定义的东西时使用。
为了对两者进行简短的比较,没有什么比听到作者自己的回应更好的了:AutoMapper与ValueInjecter
就我个人而言,我发现ValueInjector使用起来更快,同时总体上有更多的控制,但我也发现它的可读性/持续性比AutoMapper差得多,AutoMapper可能需要更多的代码才能实现类似的目标。因此,我会选择你和/或你的团队更喜欢的语法,以及你能多么容易地掌握概念,而不是你真正需要的力量。
所以我有同样的miff。。。我不能说我已经对我的解决方案进行了基准测试,但它似乎运行得相当快。。。
3位:
public static T Transform<T>(this object convertFrom) where T : class, new()
{
return (T) (new ServiceExtension().Transform(convertFrom, typeof (T)));
}
private class ServiceExtension
{
public object Transform(object convertFrom, Type convertTo)
{
object _t = Activator.CreateInstance(convertTo);
if (convertFrom == null) return _t;
var convertType = convertFrom.GetType();
foreach (
var property in _t.GetType().GetProperties().Where(f => f.CanWrite && f.GetSetMethod(true).IsPublic)
)
{
if (property.GetCustomAttributes(typeof (TransformAttribute), true).Any())
{
var transform =
(property.GetCustomAttributes(typeof (TransformAttribute), true).FirstOrDefault() as
TransformAttribute);
var transformname = transform.RelatedField ?? property.Name;
if (convertType.GetProperty(transformname) == null)
throw new ArgumentException(
string.Format(
"We were unable to find property:'"{0}'" on {1}. Please check the RelativeField value on the {2} for '"{0}'"",
transformname, convertFrom.GetType().Name, convertTo.Name));
var theValue = convertType.GetProperty(transformname).GetValue(convertFrom);
if (isCollection(theValue))
{
foreach (var item in (theValue as ICollection))
{
var someVal = new object();
var newToType = property.PropertyType.GetGenericArguments().FirstOrDefault();
if (!String.IsNullOrEmpty(transform.FullyQualifiedName))
someVal =
Transform(
item.GetType().GetProperty(transform.FullyQualifiedName).GetValue(item),
newToType);
else
someVal = Transform(item, newToType);
if (property.GetValue(_t) == null)
throw new NullReferenceException(
string.Format(
"The following property:{0} is null on {1}. Likely this needs to be initialized inside of {1}'s empty constructor",
property.Name, _t.GetType().Name));
property.PropertyType.GetMethod("Add")
.Invoke(property.GetValue(_t), new[] {someVal});
//property.SetValue(_t, theValue.Transform(theValue.GetType()));
}
}
else
property.SetValue(_t, theValue);
}
//property.SetValue(_t, property.GetValue(convertFrom, null), null);
}
return _t;
}
public bool isCollection(object o)
{
return o is ICollection
|| typeof (ICollection<>).IsInstanceOfType(o);
}
}
public class TransformAttribute : Attribute
{
public string RelatedField { get; private set; }
public string FullyQualifiedName { get; set; }
public TransformAttribute()
{
}
public TransformAttribute(string relatedField)
{
RelatedField = relatedField;
}
}
使得最终结果是:myObject.Transform()
但是这些装饰可以让您解释POCO和ViewModel 之间的差异