Ejemplo n.º 1
0
        /// <summary>
        /// 深拷贝
        /// </summary>
        /// <typeparam name="TSource">源类型</typeparam>
        /// <typeparam name="TTarget">目标类型</typeparam>
        /// <param name="source"></param>
        /// <returns></returns>
        public static TTarget MapTo <TSource, TTarget>(this TSource source)
            where TTarget : class
            where TSource : class
        {
            if (Cache.MapToCache.TryGetValue($"{typeof(TSource).FullName}+{typeof(TTarget).FullName}", out Delegate deleg))
            {
                return(((Func <TSource, TTarget>)deleg)?.Invoke(source));
            }

            deleg = SmartBuilder.DynamicMethod <Func <TSource, TTarget> >(string.Empty, IL =>
            {
                if (source is IDictionary)
                {
                }
                if (source is Stream)
                {
                    var _source = IL.NewObject(IL.ArgumentRef <TSource>(0));
                    var _target = IL.NewObject(new MemoryStream());
                    _source.Call("CopyTo", _target);
                    _target.Output();
                }
                else if (source.IsClass())
                {
                    var _source = IL.NewEntity <TSource>(IL.ArgumentRef <TSource>(0));
                    var _target = IL.NewEntity <TTarget>();
                    foreach (var sourceItem in typeof(TSource).GetProperties())
                    {
                        var targetItem = typeof(TTarget).GetProperty(sourceItem.Name);
                        if (targetItem == null || sourceItem.PropertyType != targetItem.PropertyType)
                        {
                            continue;
                        }
                        _target.SetValue(sourceItem.Name, _source.GetValue(sourceItem.Name));
                    }
                    _target.Output();
                }
                else
                {
                    throw new TypeAccessException();
                }

                IL.Return();
            });

            if (!Cache.MapToCache.TryAdd($"{typeof(TSource).FullName}+{typeof(TTarget).FullName}", deleg))
            {
                throw new ArgumentException();
            }

            return(((Func <TSource, TTarget>)deleg)?.Invoke(source));
        }