惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

AI
AI
TaoSecurity Blog
TaoSecurity Blog
H
Heimdal Security Blog
Help Net Security
Help Net Security
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Microsoft Azure Blog
Microsoft Azure Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Google DeepMind News
Google DeepMind News
爱范儿
爱范儿
The Cloudflare Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
人人都是产品经理
人人都是产品经理
大猫的无限游戏
大猫的无限游戏
N
News | PayPal Newsroom
V2EX - 技术
V2EX - 技术
博客园 - 【当耐特】
D
Darknet – Hacking Tools, Hacker News & Cyber Security
S
Secure Thoughts
C
CERT Recently Published Vulnerability Notes
罗磊的独立博客
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
P
Privacy & Cybersecurity Law Blog
有赞技术团队
有赞技术团队
S
Schneier on Security
S
SegmentFault 最新的问题
Google Online Security Blog
Google Online Security Blog
H
Hacker News: Front Page
The Last Watchdog
The Last Watchdog
Schneier on Security
Schneier on Security
PCI Perspectives
PCI Perspectives
IT之家
IT之家
Project Zero
Project Zero
博客园 - 司徒正美
P
Privacy International News Feed
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Jina AI
Jina AI
Security Latest
Security Latest
Hacker News - Newest:
Hacker News - Newest: "LLM"
腾讯CDC
C
CXSECURITY Database RSS Feed - CXSecurity.com
阮一峰的网络日志
阮一峰的网络日志
C
Check Point Blog
aimingoo的专栏
aimingoo的专栏
V
Vulnerabilities – Threatpost
W
WeLiveSecurity
NISL@THU
NISL@THU
Webroot Blog
Webroot Blog
N
Netflix TechBlog - Medium
L
Lohrmann on Cybersecurity

博客园 - 不可以

Framework 各版本比较对 用xperf查看系统启动过程 在无IIS下用SharpDevelop进行Asp.net 开发 从程序集中读取流信息 fiddler 学习笔记 IPhone 应用程序管理 Subversion配置安装 使用Windows Live Writer写博客 xml操作学习 Oracle学习 windbg学习 在博客园添加Web Live Messenger对话框 java调用C#写的com组件 配置文件加入智能提示(Intellisense)功能 让相同的winform程序只启动一个 用户中心 - 博客园 用户中心 - 博客园 可以自由控制fileupload文本框与命令按钮之间的距离 去除左边数字行号工具
.net 拷贝方法
不可以 · 2009-12-17 · via 博客园 - 不可以

在.net中通常拷贝方法有如下几种:

1.浅拷贝

实现方式:

this.MemberwiseClone();

2.深拷贝

实现方式:

 MemoryStream memoryStream = newMemoryStream();

 BinaryFormatter formatter = newBinaryFormatter();

 formatter.Serialize(memoryStream, this);

 memoryStream.Position = 0;

 formatter.Deserialize(memoryStream);

3.另类拷贝:两个对象都已存在,只将其公共数据复制过去

实现方式:利用动态代码的得反射方法,然后将所有公共数据复制

引用地址:Dynamic Code Generation

1.DynamicMethodCompiler.cs

using System;
using System.Reflection;
using System.Reflection.Emit;

namespace DynamicCompilationSpike
{
    public delegate object GetHandler(object source);
    public delegate void SetHandler(object source, object value);
    public delegate object InstantiateObjectHandler();

    public sealed class DynamicMethodCompiler
    {
        // DynamicMethodCompiler
        private DynamicMethodCompiler() { }

        // CreateInstantiateObjectDelegate
        internal static InstantiateObjectHandler CreateInstantiateObjectHandler(Type type)
        {
            ConstructorInfo constructorInfo = type.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[0], null);
            if (constructorInfo == null)
            {
                throw new ApplicationException(string.Format("The type {0} must declare an empty constructor (the constructor may be private, internal, protected, protected internal, or public).", type));
            }

            DynamicMethod dynamicMethod = new DynamicMethod("InstantiateObject", MethodAttributes.Static | MethodAttributes.Public, CallingConventions.Standard, typeof(object), null, type, true);
            ILGenerator generator = dynamicMethod.GetILGenerator();
            generator.Emit(OpCodes.Newobj, constructorInfo);
            generator.Emit(OpCodes.Ret);
            return (InstantiateObjectHandler)dynamicMethod.CreateDelegate(typeof(InstantiateObjectHandler));
        }
        
        // CreateGetDelegate
        internal static GetHandler CreateGetHandler(Type type, PropertyInfo propertyInfo)
        {
            MethodInfo getMethodInfo = propertyInfo.GetGetMethod(true);
            DynamicMethod dynamicGet = CreateGetDynamicMethod(type);
            ILGenerator getGenerator = dynamicGet.GetILGenerator();

            getGenerator.Emit(OpCodes.Ldarg_0);
            getGenerator.Emit(OpCodes.Call, getMethodInfo);
            BoxIfNeeded(getMethodInfo.ReturnType, getGenerator);
            getGenerator.Emit(OpCodes.Ret);

            return (GetHandler)dynamicGet.CreateDelegate(typeof(GetHandler));
        }

        // CreateGetDelegate
        internal static GetHandler CreateGetHandler(Type type, FieldInfo fieldInfo)
        {
            DynamicMethod dynamicGet = CreateGetDynamicMethod(type);
            ILGenerator getGenerator = dynamicGet.GetILGenerator();

            getGenerator.Emit(OpCodes.Ldarg_0);
            getGenerator.Emit(OpCodes.Ldfld, fieldInfo);
            BoxIfNeeded(fieldInfo.FieldType, getGenerator);
            getGenerator.Emit(OpCodes.Ret);

            return (GetHandler)dynamicGet.CreateDelegate(typeof(GetHandler));
        }

        // CreateSetDelegate
        internal static SetHandler CreateSetHandler(Type type, PropertyInfo propertyInfo)
        {
            MethodInfo setMethodInfo = propertyInfo.GetSetMethod(true);
            DynamicMethod dynamicSet = CreateSetDynamicMethod(type);
            ILGenerator setGenerator = dynamicSet.GetILGenerator();

            setGenerator.Emit(OpCodes.Ldarg_0);
            setGenerator.Emit(OpCodes.Ldarg_1);
            UnboxIfNeeded(setMethodInfo.GetParameters()[0].ParameterType, setGenerator);
            setGenerator.Emit(OpCodes.Call, setMethodInfo);
            setGenerator.Emit(OpCodes.Ret);

            return (SetHandler)dynamicSet.CreateDelegate(typeof(SetHandler));
        }

        // CreateSetDelegate
        internal static SetHandler CreateSetHandler(Type type, FieldInfo fieldInfo)
        {
            DynamicMethod dynamicSet = CreateSetDynamicMethod(type);
            ILGenerator setGenerator = dynamicSet.GetILGenerator();

            setGenerator.Emit(OpCodes.Ldarg_0);
            setGenerator.Emit(OpCodes.Ldarg_1);
            UnboxIfNeeded(fieldInfo.FieldType, setGenerator);
            setGenerator.Emit(OpCodes.Stfld, fieldInfo);
            setGenerator.Emit(OpCodes.Ret);

            return (SetHandler)dynamicSet.CreateDelegate(typeof(SetHandler));
        }

        // CreateGetDynamicMethod
        private static DynamicMethod CreateGetDynamicMethod(Type type)
        {
            return new DynamicMethod("DynamicGet", typeof(object), new Type[] { typeof(object) }, type, true);
        }

        // CreateSetDynamicMethod
        private static DynamicMethod CreateSetDynamicMethod(Type type)
        {
            return new DynamicMethod("DynamicSet", typeof(void), new Type[] { typeof(object), typeof(object) }, type, true);
        }

        // BoxIfNeeded
        private static void BoxIfNeeded(Type type, ILGenerator generator)
        {
            if (type.IsValueType)
            {
                generator.Emit(OpCodes.Box, type);
            }
        }

        // UnboxIfNeeded
        private static void UnboxIfNeeded(Type type, ILGenerator generator)
        {
            if (type.IsValueType)
            {
                generator.Emit(OpCodes.Unbox_Any, type);
            }
        }
    }
}

2.FastClone.cs

using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using DynamicCompilationSpike;

namespace DynamicCompilationSpike;
{
    public class FastClone
    {
        private static Dictionary<Type, FastType> __propertyCache = new Dictionary<Type, FastType>();


        /// <summary>
        /// 添加需要克隆的类型
        /// </summary>
        /// <param name="type"></param>
        /// <param name="copyPrivate">是否拷贝私有,只读字段数据</param>
        public static void AddCloneType(Type type,bool copyPrivate)
        {
            if (!__propertyCache.ContainsKey(type))
                __propertyCache.Add(type, new FastType(type,copyPrivate));

        }

        /// <summary>
        /// 只克隆对象所有数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="src"></param>
        /// <param name="target"></param>
        public static void Clone<T>(T src, T target) 
        {
            FastType fastType = __propertyCache[typeof(T)];
            foreach (MemberInfo varMember in fastType.Members)
            {
                if (!fastType.Sets.ContainsKey(varMember)) continue;
                SetHandler setHandler=  fastType.Sets[varMember];

                if (!fastType.Gets.ContainsKey(varMember)) continue;
                GetHandler getHandler = fastType.Gets[varMember];

                setHandler(target, getHandler(src));
            }
        }
    }

    internal class FastType
    {
        private Type _type;

        internal Type Type
        {
            get { return _type; }
        }

        private Dictionary<MemberInfo, SetHandler> _cacheSets = new Dictionary<MemberInfo, SetHandler>();

        public Dictionary<MemberInfo, SetHandler> Sets
        {
            get { return _cacheSets; }
        }
        private Dictionary<MemberInfo, GetHandler> _cacheGets = new Dictionary<MemberInfo, GetHandler>();

        public Dictionary<MemberInfo, GetHandler> Gets
        {
            get { return _cacheGets; }
        }

        private List<MemberInfo> _cacheMember = new List<MemberInfo>();

        public List<MemberInfo> Members
        {
            get { return _cacheMember; }
        }

        internal FastType(Type type,bool copyPrivate)
        {
            _type = type;

            foreach (PropertyInfo varProperty in type.GetProperties())
            {
                SetHandler setHandler = DynamicMethodCompiler.CreateSetHandler(type, varProperty);
                GetHandler getHandler = DynamicMethodCompiler.CreateGetHandler(type, varProperty);

                if (copyPrivate)
                {
                    _cacheSets.Add(varProperty, setHandler);
                    _cacheGets.Add(varProperty, getHandler);
                }
                else
                {
                    if (varProperty.CanWrite) _cacheSets.Add(varProperty, setHandler);
                    if (varProperty.CanRead) _cacheGets.Add(varProperty, getHandler);
                }
               
                _cacheMember.Add(varProperty);
            }

            foreach (FieldInfo varField in type.GetFields())
            {
                SetHandler setHandler = DynamicMethodCompiler.CreateSetHandler(type, varField);
                GetHandler getHandler = DynamicMethodCompiler.CreateGetHandler(type, varField);

                if (copyPrivate)
                {
                    _cacheSets.Add(varField, setHandler);
                }
                else
                {
                    if (!(varField.IsInitOnly || varField.IsLiteral)) _cacheSets.Add(varField, setHandler);
                }                
                _cacheGets.Add(varField, getHandler);
                _cacheMember.Add(varField);
            }
        }
    }
}

3.program.cs

using System;
using System.Collections.Generic;
using System.Text;
using CodeTimer1;

namespace DynamicCompilationSpike
{
    class program
    {
        public static void  Main()
        {
            InfoTest info= new InfoTest("info1");
            info.IntValue = 100;
            info.LongValue = 20000;
            info.StringValue = "中华人民共和国!";
            info.DateTimeValue = DateTime.Now.AddHours(24);
            info.DecimalValue = 600;

            InfoTest info2=null;
            long i= 0;

            CodeTimer.Time("copy:", 1000000, delegate {
                info2 = new InfoTest(i.ToString());
                i++;
                info2.IntValue = info.IntValue;
                info2.LongValue = info.LongValue;
                info2.StringValue = info.StringValue;
                info2.DateTimeValue = info.DateTimeValue;
                info2.DecimalValue = info.DecimalValue;
                info2.LastName = info.LastName;
            });
            Console.WriteLine(info2);

            InfoTest info3 = null;
            FastClone.AddCloneType(typeof(InfoTest),false);
            i = 0;
            CodeTimer.Time("clone:", 1000000, delegate
            {
                info3= new InfoTest(i.ToString());
                i++;
                FastClone.Clone<InfoTest>(info, info3);
            });
            Console.WriteLine(info3);
            Console.ReadKey();

        }
    }
}

4.CodeTimer代码地址

5.性能参数对比

image