编辑:这最初用于 1:1 映射,但我发现我需要更复杂的递归映射,所以在这里发布了一个新问题:How to recursively map entity to view model with Automapper function call?
我正在尝试使用 ServiceStack ConvertTo<> 方法将实体类函数一般映射到 View 模型。这映射了所有相似的类型和属性名称并且工作正常,但我想找到一种方法将函数的结果映射到属性。这是一些代码
实体示例:
public class Item {
public long Id {get; set;}
public List<Product> GetProducts() {
return Repository.GetAll<Product>();
}
}
View 模型示例:
public class ItemViewModel {
public long Id {get;set;}
public List<Product> Products {get; set;}
}
理想的结果是有一个映射函数,该函数在实体类中查找与返回类型匹配且函数名称为“Get”+属性名称的方法,然后执行它并将结果映射到 View 模型。
最佳答案
虽然您可能会找到类似 Automapper 的内容或 Value Injecter可能已经包含此功能,没有什么可以阻止您编写一个快速的小实用方法:
public TTarget MapToViewModel<TSource, TTarget>(TSource source)
where TTarget : new()
{
var sourceType = source.GetType();
var targetProperties = typeof(TTarget).GetProperties(BindingFlags.Public | BindingFlags.Instance);
var sourceProperties = sourceType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
var sourceMethods = sourceType.GetMethods(BindingFlags.Public | BindingFlags.Instance);
var target = Activator.CreateInstance<TTarget>();
foreach (var prop in targetProperties)
{
var sourceProp = sourceProperties.FirstOrDefault(x => x.Name == prop.Name);
if (sourceProp != null)
{
prop.SetValue(target, sourceProp.GetValue(source, null), null);
}
else
{
var sourceMethod = sourceMethods.FirstOrDefault(x => x.Name == "Get" + prop.Name);
if (sourceMethod != null)
{
prop.SetValue(target, sourceMethod.Invoke(source, null), null);
}
}
}
return target;
}
上面 .FirstOrDefault
调用中的条件仅使用 Name
,但您可以将它们扩展为您喜欢的任何内容。
要使用它,只需这样调用它:
var itemViewModel = MapToViewModel<Item, ItemViewModel>(item);
如果您的常规模型中的方法有任何参数,请小心。如果您发现您的模型太复杂(或不遵循一两个命名约定),那么使用 AutoMapper 之类的东西可能会更好。不过,对于简单的映射,像这样的东西应该可以完成这项工作。
关于c# - 如何自动将 .NET 函数调用映射到属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20571157/