什么是绘制同一类型排除某些领域的两个对象的最佳方式? [英] What is the best way to map two objects of the same type excluding some fields?

查看:139
本文介绍了什么是绘制同一类型排除某些领域的两个对象的最佳方式?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我以前这里张贴我的问题,但我没有得到任何答复的原因 - 我猜 - 它太普通。我会试着更简洁。

I've previously post my question here but I didn't get any reply cause - I guess - it's too generic. I'll try to be more concise.

我已经得到了两个同类型的对象,我要地图的某些属性,并排除他人。我所试图做的是保存对象在缓存中,后来把它拿来,仅使用属性(田)的特定属性。

I've got two object of the same type and I want to map some of the properties and exclude others. What I am trying to do is save an object in a cache and fetch it later, using only the properties (fields) with a specific attribute.

我有一个看的 Automapper ,但我没有发现任何东西,这似乎是适合我,所以我一直认为实现我自己的系统结果
我已经创建了一个属性:

I've had a look at Automapper but I haven't found anything which seems to be suitable for me so I've thought to implement my own system.
I've created an attribute:

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

和装饰,一类是在我需要包括以下字段:

and decorated a class with it on the fields I need to include:

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; }

    ...
} 

现在,我已经实现的功能,它负责的映射:

Now, I've implemented a function which is responsible for the mapping:

    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);
    }

现在,当我需要从缓存中读取我的视图模型,只有填写属性标记属性我的代码如下所示:

Now, when I need to fetch my viewmodel from the cache and fill only the properties marked with the attribute my code looks like this:

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



我不知道这是最好的做,但看来我的唯一途径找到。结果
任何建议,将不胜感激。

I don't know if this is the best to do it but it seems the only way I have found.
Any suggestion would be appreciated.

推荐答案

使用直接反映(如上例)将是的 sloooow 的;给人一种更完整的答案是棘手的,因为它取决于你是否希望有一个浅克隆或子对象的深克隆。无论哪种方式,你应该想到这涉及一些元编程和缓存 - 无论是使用的ILGenerator或表达

Using direct reflection (as in the example) will be sloooow; giving a more complete answer is tricky, as it depends on whether you want a shallow clone or deep clone of sub-objects. Either way, you should expect this to involve some meta-programming and caching - using either ILGenerator or Expression.

然而,对于一个懒惰的选项,系列化可能是有用的。许多串行器允许您使用属性包含/排除特定项目;通过序列化到一个内存流,复卷( .POSITION = 0 )和反序列化,你应该得到的只是你所选择的会员的深层副本。

However, for a lazy option, serialization might be useful. A number of serializers allow you to use attributes to include/exclude particular items; by serializing to a memory-stream, rewinding (.Position=0) and deserializing you should get a deep copy of just your chosen members.

下面是一个使用一个例子表达式

Here's an example using 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);
    }
} 

这篇关于什么是绘制同一类型排除某些领域的两个对象的最佳方式?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆