C# 将实体转换为viewmodels以与web api一起使用
我目前正在努力寻找一种更好的方法,用我的C# 将实体转换为viewmodels以与web api一起使用,c#,entity-framework,asp.net-mvc-4,asp.net-web-api,C#,Entity Framework,Asp.net Mvc 4,Asp.net Web Api,我目前正在努力寻找一种更好的方法,用我的Entitiy对象填充我的ViewModel对象。我有以下webapicontroller方法: [HttpGet] public IEnumerable<ClientSearchViewModel> FindClients(string query) { var clients = _clientService.SearchClient(query).ToList(); var returnClients = new List
Entitiy
对象填充我的ViewModel
对象。我有以下webapi
controller方法:
[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;
}
除了查看返回对象列表并创建新的
ViewModel
列表之外,还有其他方法吗?我强烈建议使用映射插件来实现此目的,例如:
或
这样的插件将允许您在内部或数据层中使用的对象与外部对象(DTO/ViewModels)之间进行映射。它们可以直接处理许多事情,例如自动映射具有相同类型的任何类似命名属性,但也允许在属性或类型的特定映射中进行大量控制,以便在需要更自定义的时候使用
为了对两者进行简单的比较,没有什么比听到作者自己的回答更好的了:
就我个人而言,我发现ValueInjector使用起来更快,同时总体控制能力更强,但我也发现它的可读性/直观性远不如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;
}
}
publicstatict转换(此对象转换自),其中T:class,new()
{
return(T)(newServiceExtension().Transform(convertFrom,typeof(T)));
}
私有类服务扩展
{
公共对象转换(对象convertFrom,类型convertTo)
{
对象_t=Activator.CreateInstance(convertTo);
if(convertFrom==null)返回_t;
var convertType=convertFrom.GetType();
弗雷奇(
_t.GetType().GetProperties()中的var属性,其中(f=>f.CanWrite&&f.GetSetMethod(true.IsPublic)
)
{
if(property.GetCustomAttributes(typeof(TransformAttribute),true).Any())
{
变量变换=
(property.GetCustomAttributes(typeof(TransformAttribute),true).FirstOrDefault()作为
转换属性);
var transformname=transform.RelatedField??property.Name;
if(convertType.GetProperty(transformname)==null)
抛出新的ArgumentException(
字符串格式(
“我们在{1}上找不到属性:\”{0}\。请检查{2}上的RelativeField值是否为\“{0}\”,
transformname,convertFrom.GetType().Name,convertTo.Name));
var theValue=convertType.GetProperty(transformname).GetValue(convertFrom);
如果(是集合(值))
{
foreach(中的var项目(作为ICollection的值))
{
var someVal=新对象();
var newToType=property.PropertyType.GetGenericArguments().FirstOrDefault();
如果(!String.IsNullOrEmpty(transform.FullyQualifiedName))
某地=
转化(
item.GetType().GetProperty(transform.FullyQualifiedName).GetValue(item),
新类型);
其他的
someVal=转换(项,新类型);
if(property.GetValue(\u t)==null)
抛出新的NullReferenceException(
字符串格式(
“以下属性:{0}在{1}上为空。这可能需要在{1}的空构造函数内初始化”,
property.Name,_t.GetType().Name));
property.PropertyType.GetMethod(“添加”)
.Invoke(property.GetValue(_t),new[]{someVal});
//属性.SetValue(_t,theValue.Transform(theValue.GetType());
}
}
其他的
属性设置值(_t,theValue);
}
//SetValue(_t,property.GetValue(convertFrom,null),null);
}
返回;;
}
公共布尔isCollection(对象o)
{
返回o是I集合
||typeof(i收集)。i安装类型(o);
}
}
公共类TransformAttribute:属性
{
公共字符串相关字段{get;private set;}
公共字符串FullyQualifiedName{get;set;}
公共属性()
{
}
公共转换属性(字符串相关字段)
{
RelatedField=RelatedField;
}
}
最终结果是:myObject.Transform()
但是这些装饰让您可以解释POCO和ViewModel之间的差异个人是否喜欢其中一个?或者两者都有一些简单的优点和缺点?添加了一个链接,其中包含来自实际作者的更多信息。
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;
}
}