首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > C# >

对类的某个步骤临时改写的代码排错

2013-11-01 
对类的某个方法临时改写的代码排错在我询问 “代码中能否对类的某个方法临时改写”,sbwwkmyd 给出其中一种方

对类的某个方法临时改写的代码排错
在我询问 “代码中能否对类的某个方法临时改写”,sbwwkmyd 给出其中一种方案的代码,
using System;

namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {
            ClsAAA aaa = new ClsAAA();

            using (methodWriter32<Action> method = new methodWriter32<Action>(aaa.ff, new Program().nothing)) 
            {
                aaa.ff();
            }
            Console.ReadKey();
        }

        public void nothing()
        {
        }
    }

    class ClsAAA
    {
        public void ff()
        {
            Console.WriteLine("OK");
        }
    }

    [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit)]
    internal struct unionMethod
    {
        internal class point
        {
            public int Point;
        }

        [System.Runtime.InteropServices.FieldOffset(0)]
        public point Point;
        [System.Runtime.InteropServices.FieldOffset(0)]
        public object Method;
    }

    internal unsafe struct methodTarget
    {
        public int* MethodPoint;
        public object Target;
        public int* TargetPoint;
    }

    internal class targetPoint
    {
        public object Target;
    }

    public unsafe abstract class methodWriterBase32<methodType> : IDisposable
    {
        private int* methodPoint;
        private int method;
        public methodWriterBase32(methodType setMethod, methodType getMethod)
        {
            if (setMethod == null || getMethod == null) throw null;
            methodPoint = getPoint(setMethod);
            int* getMethodPoint = getPoint(getMethod);
            if (methodPoint == getMethodPoint) throw null;
            method = *methodPoint;
            *methodPoint = *getMethodPoint;
        }

        protected abstract int* getPoint(methodType method);
        public void Set(methodType method)
        {
            if (method == null) throw null;
            *methodPoint = *getPoint(method);
        }

        public void Dispose()
        {
            if (method != 0)
            {
                *methodPoint = method;
                method = 0;
            }
        }


    }

    public sealed unsafe class staticMethodWriter32<methodType> : methodWriterBase32<methodType>
    {
        public staticMethodWriter32(methodType setMethod, methodType getMethod) : base(setMethod, getMethod) { }
        protected override int* getPoint(methodType method)
        {
            Delegate methodDelegate = method as Delegate;
            if (!methodDelegate.Method.IsStatic) throw null;
            unionMethod union = new unionMethod { Method = method };
            return (int*)*((int*)*((int*)union.Point.Point + 4) + 2) + 2;
        }
    }

    public sealed unsafe class methodWriter32<methodType> : methodWriterBase32<methodType>
    {
        public methodWriter32(methodType setMethod, methodType getMethod) : base(setMethod, getMethod) { }
        protected override int* getPoint(methodType method)
        {
            Delegate methodDelegate = method as Delegate;
            if (methodDelegate.Method.IsStatic) throw null;
            unionMethod union = new unionMethod { Method = method };
            int point = union.Point.Point;
            int* methodPoint = (int*)point;
            while (*methodPoint != point) ++methodPoint;
            return (int*)*((int*)*(methodPoint + 2) + 2) + 2;
        }
    }
}
但我在.NET3.5环境下,不安全代码选择打勾,程序运行出错,
在类 methodWriterBase32 的构建函数中 method = *methodPoint; 这句话,错误信息:
“尝试读取或写入受保护的内存。这通常指示其他内存已损坏”

我也试着改为 .NET 2.0 但它不允许这种写法:
using (methodWriter32<Action> method = new methodWriter32<Action>(aaa.ff, new ClsBBB().ff)) 

也试着两个分成两个项目,一个用2.0,一个用3.5,仍然是 method = *methodPoint; 这句话同样错误。
我对C#中指针不熟悉,大家能帮我看一下是什么原因吗?

[解决办法]
我#19代码中联合体的定义是错误的,指针定位也是错误的。可以参考fastCSharp.reflection.methodWriter,我这里给个重新写个只支持32位的简易版本

        /// <summary>
        /// 委托方法与指针联合体
        /// </summary>
        [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Explicit)]
        internal struct methodPointUnion
        {
            /// <summary>
            /// 委托方法
            /// </summary>
            internal sealed class method
            {
                /// <summary>
                /// 委托方法
                /// </summary>
                public object Method;
            }
            /// <summary>
            /// 委托指针
            /// </summary>
            private sealed class point


            {
                /// <summary>
                /// 委托指针
                /// </summary>
                public int Point;
            }
            /// <summary>
            /// 委托指针
            /// </summary>
            [System.Runtime.InteropServices.FieldOffset(0)]
            private point methodPoint;
            /// <summary>
            /// 委托方法
            /// </summary>
            [System.Runtime.InteropServices.FieldOffset(0)]
            public method Method;
            /// <summary>
            /// 委托指针
            /// </summary>
            public unsafe int* Point
            {
                get
                {
                    int* point = (int*)methodPoint.Point + 4;
                    if (*point == 0) --point;
                    return (int*)*((int*)*point + 2) + 2;
                }
            }
        }
        /// <summary>
        /// 方法重写
        /// </summary>
        /// <typeparam name="methodType">委托类型</typeparam>
        public sealed unsafe class methodWriter<methodType> : IDisposable
        {
            /// <summary>
            /// 方法指针
            /// </summary>
            private int* methodPoint;
            /// <summary>
            /// 方法指针值
            /// </summary>
            private int method;
            /// <summary>
            /// 是否静态方法
            /// </summary>
            private bool isStatic;
            /// <summary>
            /// 方法重写
            /// </summary>
            /// <param name="method">被重写方法委托</param>
            /// <param name="setMethod">待写入的方法委托</param>
            public methodWriter(methodType method, methodType setMethod)
            {
                Delegate methodDelegate = method as Delegate;
                if (methodDelegate == null 


[解决办法]
 setMethod == null) throw null;
                Delegate setMethodDelegate = setMethod as Delegate;
                isStatic = methodDelegate.Method.IsStatic;
                if (isStatic ^ setMethodDelegate.Method.IsStatic) throw null;
                if (!isStatic)
                {
                    if (methodDelegate.Target != null && !methodDelegate.Target.GetType().IsClass) throw null;
                    if (setMethodDelegate.Target != null && !methodDelegate.Target.GetType().IsClass) throw null;
                }
                methodPointUnion union = new methodPointUnion { Method = new methodPointUnion.method { Method = methodDelegate } };
                int* methodPoint = union.Point;
                union.Method.Method = setMethodDelegate;
                int* setMethodPoint = union.Point;
                if (methodPoint == setMethodPoint) throw null;
                this.method = *(this.methodPoint = methodPoint);
                *methodPoint = *setMethodPoint;
            }
            /// <summary>
            /// 方法重写
            /// </summary>
            /// <param name="setMethod">待写入的方法委托</param>
            public void Set(methodType setMethod)
            {
                Delegate setMethodDelegate = setMethod as Delegate;
                if (setMethodDelegate == null) throw null;
                if (isStatic ^ setMethodDelegate.Method.IsStatic) throw null;
                if (!isStatic && setMethodDelegate.Target != null && !setMethodDelegate.Target.GetType().IsClass) throw null;
                methodPointUnion union = new methodPointUnion { Method = new methodPointUnion.method { Method = setMethodDelegate } };
                *methodPoint = *union.Point;
            }
            /// <summary>
            /// 释放方法指针
            /// </summary>
            public void Dispose()
            {
                int method = this.method;
                this.method = 0;
                if (method != 0) *methodPoint = method;
            }
        }

        class ClsAAA
        {
            public void ff()
            {


                Console.WriteLine("OK");
            }
        }
        public void nothing()
        {
        }
        static void Main(string[] args)
        {

            ClsAAA aaa = new ClsAAA();
            using (methodWriter<action> method = new methodWriter<action>(aaa.ff, new Program().nothing))
            {
                aaa.ff();
            }
            Console.ReadKey();
        }

引用:
这种方法除了展示一种特别的技巧以外,基本没有什么实际意义,对于你做mock来说。
技巧确实是没有意义的,我写程序都是为了更方便的解决实际问题。

热点排行