123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Collections;
- using System.Runtime.Serialization;
- using System.Runtime.Serialization.Formatters.Binary;
- using System.IO;
- using System.Text.Json;
- using System.ComponentModel;
- using System.Reflection;
- namespace EasyDevCore.Common
- {
- /// <summary>
- ///
- /// </summary>
- public static class CopyHelper
- {
- /// <summary>
- /// Clones the hashtable.
- /// </summary>
- /// <param name="input">The input.</param>
- /// <returns></returns>
- public static Hashtable CloneHashtable(this Hashtable input)
- {
- Hashtable ret = new Hashtable();
- foreach (DictionaryEntry dictionaryEntry in input)
- {
- if (dictionaryEntry.Value is string)
- {
- ret.Add(dictionaryEntry.Key, dictionaryEntry.Value != null ? (string)dictionaryEntry.Value : null);
- }
- else if (dictionaryEntry.Value is Hashtable)
- {
- ret.Add(dictionaryEntry.Key, CloneHashtable((Hashtable)dictionaryEntry.Value));
- }
- else if (dictionaryEntry.Value is ArrayList)
- {
- ret.Add(dictionaryEntry.Key, new ArrayList((ArrayList)dictionaryEntry.Value));
- }
- }
- return ret;
- }
- /// <summary>
- /// Clones the specified source.
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="source">The source.</param>
- /// <returns>T.</returns>
- /// <exception cref="ArgumentException">The type must be serializable.;source</exception>
- public static T CloneObject<T>(this T source)
- {
- #pragma warning disable SYSLIB0050 // Type or member is obsolete
- if (!typeof(T).IsSerializable)
- {
- throw new ArgumentException("The type must be serializable.", "source");
- }
- #pragma warning restore SYSLIB0050 // Type or member is obsolete
- // Don't serialize a null object, simply return the default for that object
- if (source == null)
- {
- return default(T);
- }
- var json = JsonSerializer.Serialize(source, source.GetType());
- return string.IsNullOrWhiteSpace(json) ? default(T) : (T)JsonSerializer.Deserialize(json, source.GetType());
- }
- /// <summary>
- /// Simples the map.
- /// </summary>
- /// <typeparam name="TDest">The type of the dest.</typeparam>
- /// <param name="source">The source.</param>
- /// <param name="updateProperties">The update properties.</param>
- /// <param name="exceptProperties">The except properties.</param>
- /// <returns></returns>
- public static TDest SimpleMap<TDest>(this object source, string updateProperties = null, string exceptProperties = null)
- where TDest : class, new()
- {
- var dest = new TDest();
- return SimpleMap<TDest>(source, dest, updateProperties, exceptProperties);
- }
- /// <summary>
- /// Simples the map.
- /// </summary>
- /// <typeparam name="TDest">The type of the dest.</typeparam>
- /// <param name="source">The source.</param>
- /// <param name="destination">The destination.</param>
- /// <param name="updateProperties">The update properties.</param>
- /// <param name="exceptProperties">The except properties.</param>
- /// <returns></returns>
- public static TDest SimpleMap<TDest>(this object source, TDest destination, string updateProperties = null, string exceptProperties = null)
- where TDest : class
- {
- Type destType = destination.GetType();
- Span<PropertyInfo> sourceProperties = null;
- if(string.IsNullOrWhiteSpace(updateProperties))
- {
- sourceProperties = source.GetType().GetProperties().Where(x => x.CanRead).ToArray().AsSpan();
- }
- else
- {
- sourceProperties = (from sp in source.GetType().GetProperties().Where(x => x.CanRead)
- join propName in updateProperties.Split(',') on sp.Name equals propName
- select sp).ToArray().AsSpan();
- }
- Span<PropertyInfo> destinationProperties = null;
- if (string.IsNullOrWhiteSpace(exceptProperties))
- {
- destinationProperties = destType.GetProperties().Where(x => x.CanWrite).ToArray().AsSpan();
- }
- else
- {
- var exceptPropertiesArray = exceptProperties.Split(',');
- destinationProperties = destType.GetProperties().Where(x => exceptPropertiesArray.Contains(x.Name)).Where(x => x.CanWrite).ToArray().AsSpan();
- }
- for (int si = 0; si < sourceProperties.Length; si++)
- {
- PropertyInfo sourceProperty = sourceProperties[si];
- for (int di = 0; di < destinationProperties.Length; di++)
- {
- PropertyInfo destinationProperty = destinationProperties[di];
- if (sourceProperty.Name.Equals(destinationProperty.Name, StringComparison.InvariantCultureIgnoreCase))
- {
- var sourceValue = sourceProperty.GetValue(source);
- destinationProperty.SetValue(destination, sourceProperty.PropertyType == destinationProperty.PropertyType ? sourceValue : sourceValue.ChangeType(destType));
- break;
- }
- }
- }
- return destination;
- }
- /// <summary>
- /// Copies the specified source.
- /// </summary>
- /// <typeparam name="TSource">The type of the source.</typeparam>
- /// <typeparam name="TDest">The type of the dest.</typeparam>
- /// <param name="dest">The dest.</param>
- /// <param name="source">The source.</param>
- /// <param name="caseSensitive">if set to <c>true</c> [case sensitive].</param>
- /// <param name="predicate">The predicate.</param>
- /// <param name="setter">The setter.</param>
- /// <returns></returns>
- public static TDest Copy<TSource, TDest>(this TDest dest, TSource source, bool caseSensitive = false, Func<string, object, bool> predicate = null, Func<string, object, object> setter = null)
- where TSource : class
- where TDest : class
- {
- if (source.IsDictionary() && source.HasGenerictArgumentType<string>(0))
- {
- var props = TypeDescriptor.GetProperties(dest);
- var machingNames = from prop in props.OfType<PropertyDescriptor>()
- from val in (IDictionary<string, object>)source
- where prop.Name.Equals(val.Key, (caseSensitive ? StringComparison.InvariantCulture : StringComparison.InvariantCultureIgnoreCase))
- && (predicate == null || predicate(prop.Name, val.Value))
- select new { Property = prop, Value = val.Value };
- machingNames.ForEach(m => ReflectionHelper.SetPropertyValue(dest, m.Property, (setter == null ? m.Value : setter(m.Property.Name, m.Value))));
- }
- else
- {
- var sourceProps = TypeDescriptor.GetProperties(source);
- var destProps = TypeDescriptor.GetProperties(dest);
- var machingProps = from s in sourceProps.OfType<PropertyDescriptor>()
- from d in destProps.OfType<PropertyDescriptor>()
- where s.Name.Equals(d.Name, (caseSensitive ? StringComparison.InvariantCulture : StringComparison.InvariantCultureIgnoreCase))
- && (predicate == null || predicate(d.Name, s.GetValue(source)))
- select new { SourceProp = s, DestProp = d };
- machingProps.ForEach(m =>
- {
- var value = m.SourceProp.GetValue(source);
- ReflectionHelper.SetPropertyValue(dest, m.DestProp, (setter == null ? value : setter(m.DestProp.Name, value)));
- });
- }
- return dest;
- }
- }
- }
|