栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

将属性值从一个对象自动应用于另一个相同类型的对象?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

将属性值从一个对象自动应用于另一个相同类型的对象?

我有一个

MiscUtil
叫作
PropertyCopy
类似操作的类型-
尽管它创建了目标类型的新实例并将属性复制到其中。

它不需要类型相同-只是将所有可读属性从“源”类型复制到“目标”类型。当然,如果类型相同,那更可能起作用:)它是一个浅表副本,顺便说一句。

在此答案底部的代码块中,我扩展了类的功能。要从一个实例复制到另一个实例,它

PropertyInfo
在执行时使用简单的值-
这比使用表达式树要慢,但是另一种选择是编写一个动态方法,我不太喜欢这种方法。如果性能对您绝对至关重要,请让我知道,我会解决的。要使用该方法,请编写如下内容:

MyType instance1 = new MyType();// Do stuffMyType instance2 = new MyType();// Do stuffPropertyCopy.Copy(instance1, instance2);

(哪里

Copy
是使用类型推断的通用方法)。

我还没有准备好完整的MiscUtil版本,但是这里是更新的代码,包括注释。我不会为SO编辑器重新包装它们-只需复制整个块即可。

(如果我从头开始,我可能还会在命名方面对API进行一些重新设计,但我不想破坏现有的用户…)

#if DOTNET35using System;using System.Collections.Generic;using System.Linq.expressions;using System.Reflection;namespace MiscUtil.Reflection{    /// <summary>    /// Non-generic class allowing properties to be copied from one instance    /// to another existing instance of a potentially different type.    /// </summary>    public static class PropertyCopy    {        /// <summary>        /// Copies all public, readable properties from the source object to the        /// target. The target type does not have to have a parameterless constructor,        /// as no new instance needs to be created.        /// </summary>        /// <remarks>only the properties of the source and target types themselves        /// are taken into account, regardless of the actual types of the arguments.</remarks>        /// <typeparam name="TSource">Type of the source</typeparam>        /// <typeparam name="TTarget">Type of the target</typeparam>        /// <param name="source">Source to copy properties from</param>        /// <param name="target">Target to copy properties to</param>        public static void Copy<TSource, TTarget>(TSource source, TTarget target) where TSource : class where TTarget : class        { PropertyCopier<TSource, TTarget>.Copy(source, target);        }    }    /// <summary>    /// Generic class which copies to its target type from a source    /// type specified in the Copy method. The types are specified    /// separately to take advantage of type inference on generic    /// method arguments.    /// </summary>    public static class PropertyCopy<TTarget> where TTarget : class, new()    {        /// <summary>        /// Copies all readable properties from the source to a new instance        /// of TTarget.        /// </summary>        public static TTarget CopyFrom<TSource>(TSource source) where TSource : class        { return PropertyCopier<TSource, TTarget>.Copy(source);        }    }    /// <summary>    /// Static class to efficiently store the compiled delegate which can    /// do the copying. We need a bit of work to ensure that exceptions are    /// appropriately propagated, as the exception is generated at type initialization    /// time, but we wish it to be thrown as an ArgumentException.    /// Note that this type we do not have a constructor constraint on TTarget, because    /// we only use the constructor when we use the form which creates a new instance.    /// </summary>    internal static class PropertyCopier<TSource, TTarget>    {        /// <summary>        /// Delegate to create a new instance of the target type given an instance of the        /// source type. This is a single delegate from an expression tree.        /// </summary>        private static readonly Func<TSource, TTarget> creator;        /// <summary>        /// List of properties to grab values from. The corresponding targetProperties         /// list contains the same properties in the target type. Unfortunately we can't        /// use expression trees to do this, because we basically need a sequence of statements.        /// We could build a DynamicMethod, but that's significantly more work :) Please mail        /// me if you really need this...        /// </summary>        private static readonly List<PropertyInfo> sourceProperties = new List<PropertyInfo>();        private static readonly List<PropertyInfo> targetProperties = new List<PropertyInfo>();        private static readonly Exception initializationException;        internal static TTarget Copy(TSource source)        { if (initializationException != null) {     throw initializationException; } if (source == null) {     throw new ArgumentNullException("source"); } return creator(source);        }        internal static void Copy(TSource source, TTarget target)        { if (initializationException != null) {     throw initializationException; } if (source == null) {     throw new ArgumentNullException("source"); } for (int i = 0; i < sourceProperties.Count; i++) {     targetProperties[i].SetValue(target, sourceProperties[i].GetValue(source, null), null); }        }        static PropertyCopier()        { try {     creator = BuildCreator();     initializationException = null; } catch (Exception e) {     creator = null;     initializationException = e; }        }        private static Func<TSource, TTarget> BuildCreator()        { Parameterexpression sourceParameter = expression.Parameter(typeof(TSource), "source"); var bindings = new List<MemberBinding>(); foreach (PropertyInfo sourceProperty in typeof(TSource).GetProperties(BindingFlags.Public | BindingFlags.Instance)) {     if (!sourceProperty.CanRead)     {         continue;     }     PropertyInfo targetProperty = typeof(TTarget).GetProperty(sourceProperty.Name);     if (targetProperty == null)     {         throw new ArgumentException("Property " + sourceProperty.Name + " is not present and accessible in " + typeof(TTarget).FullName);     }     if (!targetProperty.CanWrite)     {         throw new ArgumentException("Property " + sourceProperty.Name + " is not writable in " + typeof(TTarget).FullName);     }     if ((targetProperty.GetSetMethod().Attributes & MethodAttributes.Static) != 0)     {         throw new ArgumentException("Property " + sourceProperty.Name + " is static in " + typeof(TTarget).FullName);     }     if (!targetProperty.PropertyType.IsAssignableFrom(sourceProperty.PropertyType))     {         throw new ArgumentException("Property " + sourceProperty.Name + " has an incompatible type in " + typeof(TTarget).FullName);     }     bindings.Add(expression.Bind(targetProperty, expression.Property(sourceParameter, sourceProperty)));     sourceProperties.Add(sourceProperty);     targetProperties.Add(targetProperty); } expression initializer = expression.MemberInit(expression.New(typeof(TTarget)), bindings); return expression.Lambda<Func<TSource, TTarget>>(initializer, sourceParameter).Compile();        }    }}#endif


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/576274.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号