读书人

代码中可否对类的某个方法临时改写

发布时间: 2013-10-24 18:27:21 作者: rapoo

代码中能否对类的某个方法临时改写?
测试代码如下:主程序实例化 ClsAAA,然后执行 aaa.ff() 这个方法。
class Program
{
static void Main(string[] args)
{
ClsAAA aaa = new ClsAAA();
//aaa.ff = ShowNothing;

aaa.ff();
Console.ReadKey();
}

private void ShowNothing()
{}
}

class ClsAAA
{
public void ff()
{
Console.WriteLine("OK");
}
}
请问有没有办法让 ff变为ShowNothing(),这样执行 aaa.ff() 实际是执行ShowNothing,不显示任何东西出来。
[解决办法]

引用:
谢谢大家的回答,不过,我没说它的相关环境,所以造成大家的误解。

我想让它应用于写“单元测试”的代码中。

因为某一个子程序总会调用好几个其它子程序,以前我有一个方案,是用标志(处于测试状态),让某些子程序跳过具体执行,并返回计划的内容,该方案存在许多缺点(比如对原代码的改写等问题)。

现在想在单元测试的代码中如果能临时改写某个类的某个方法,比如我们要测试方法一,它中间调用了方法二,如果我们测试代码中改写了方法二,最简单的就是改为空子程序。这样,我执行方法一,它实际调用的是空方法,而不是方法二,就是说我对方法一的测试,就不会涉及到 方法二。



class Program
{
static void Main(string[] args)
{
IClsAAA aaa = new ClsAAA();
//aaa.ff = ShowNothing;

aaa.ff();
Console.ReadKey();
}


}

interface IClsAAA
{
void ff();
}

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

//在测试代码中
public TestClsAAA : IClsAAA
{
public void ff()
{
ShowNothing();
}
}

private void ShowNothing()
{ }

public void TestClsAAA_ShowNothing()
{
IClsAAA aaa = new TestClsAAA();
aaa.ff();
}


[解决办法]
nuget code --> Install-Package Moq
public class ClsAAA
{
public virtual void ff()
{
Console.WriteLine("OK");
}
}
var mock = new Mock<ClsAAA>();
mock.Setup(foo => foo.ff()).Callback(() => Console.WriteLine("ShowNothing()"));
mock.Object.ff();
[解决办法]
比如32位.NET2.0的程序可以这样做
        [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;
}
}

        class ClsAAA
{
public void ff()
{
Console.WriteLine("OK");
}
}
class ClsBBB
{
public void ff()
{
}
} static void Main(string[] args)
{
ClsAAA aaa = new ClsAAA();
using (methodWriter32<Action> method = new methodWriter32<Action>(aaa.ff, new ClsBBB().ff))
{
aaa.ff();
}
Console.ReadKey();
}

读书人网 >C#

热点推荐