gpt4 book ai didi

c# - 映射两个相同类型的对象(不包括某些字段)的最佳方法是什么?

转载 作者:行者123 更新时间:2023-11-30 16:30:43 24 4
gpt4 key购买 nike

我之前已经发布了我的问题 here但我没有得到任何回复,因为 - 我猜 - 它太笼统了。我会尝试更简洁。

我有两个相同类型的对象,我想映射一些属性并排除其他属性。我想做的是将一个对象保存在缓存中,稍后再获取它,只使用具有特定属性的属性(字段)。

我看过 Automapper,但没有找到适合我的东西,所以我想实现自己的系统。
我创建了一个属性:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public class FilterFieldAttribute: Attribute
{
}

并在我需要包含的字段上用它装饰了一个类:

public class OrdersViewModel : BaseViewModel
{
...

[FilterField]
[DisplayName("Order Number:")]
public string OrderNumber { get; set; }

[FilterField]
[DisplayName("From date:")]
public DateTime FromDate { get; set; }

[FilterField]
[DisplayName("To date:")]
public DateTime ToDate { get; set; }

[DisplayName("Status:")]
public int Status { get; set; }

...
}

现在,我实现了一个负责映射的函数:

    private T Map<T>(T Source, T Destination) where T : BaseViewModel
{
if (Source == null)
{
return (Source);
}

FilterFieldAttribute filterAttribute;

foreach (PropertyInfo propInfo in typeof(T).GetProperties())
{
foreach (FilterFieldAttribute attr in propInfo.GetCustomAttributes(typeof(FilterFieldAttribute), false))
{
filterAttribute = attr as FilterFieldAttribute;
if (filterAttribute != null)
{
var value = propInfo.GetValue(Source, null);
propInfo.SetValue(Destination, value, null);
}
}
}
return (Destination);
}

现在,当我需要从缓存中获取我的 View 模型并仅填充标有属性的属性时,我的代码如下所示:

viewModel = Map<T>(myCache.Get(Key) as T, viewModel);

我不知道这是否是最好的方法,但这似乎是我找到的唯一方法。
任何建议将不胜感激。

最佳答案

使用直接反射(如示例中所示)将会慢速;给出更完整的答案很棘手,因为这取决于您是想要子对象的浅克隆还是深克隆。无论哪种方式,您都应该期望这涉及一些元编程和缓存 - 使用 ILGenerator 或 Expression。

但是,对于惰性选项,序列化可能很有用。许多序列化程序允许您使用属性来包含/排除特定项目;通过序列化到内存流、倒带 (.Position=0) 和反序列化,您应该只获得所选成员的深拷贝。

这是一个使用 Expression 的例子:

using System;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public class FilterFieldAttribute: Attribute
{
public static T Clone<T>(T obj) where T : class, new()
{
return Cache<T>.clone(obj);
}

private static class Cache<T> where T : class, new()
{
public static readonly Func<T,T> clone;
static Cache()
{
var param = Expression.Parameter(typeof(T), "source");
var members = from prop in typeof(T).GetProperties()
where Attribute.IsDefined(prop, typeof(FilterFieldAttribute))
select Expression.Bind(prop, Expression.Property(param, prop));

var newObj = Expression.MemberInit(Expression.New(typeof(T)), members);
clone = Expression.Lambda<Func<T,T>>(newObj, param).Compile();
}
}
}

public class OrdersViewModel
{
[FilterField]
[DisplayName("Order Number:")]
public string OrderNumber { get; set; }

[FilterField]
[DisplayName("From date:")]
public DateTime FromDate { get; set; }

[FilterField]
[DisplayName("To date:")]
public DateTime ToDate { get; set; }

[DisplayName("Status:")]
public int Status { get; set; }

static void Main()
{
var foo = new OrdersViewModel { OrderNumber = "abc", FromDate = DateTime.Now,
ToDate = DateTime.Now, Status = 1};
var bar = FilterFieldAttribute.Clone(foo);
}
}

关于c# - 映射两个相同类型的对象(不包括某些字段)的最佳方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5471048/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com