Skip to content

Instantly share code, notes, and snippets.

@tangdf
Last active November 27, 2017 07:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tangdf/a5e0fcd5328d06f6cbcf07475d667222 to your computer and use it in GitHub Desktop.
Save tangdf/a5e0fcd5328d06f6cbcf07475d667222 to your computer and use it in GitHub Desktop.
Callvirt vs Call
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
using AspectCore.Extensions.Reflection.Emit;
using Xunit;
namespace AspectCore.Extensions.Reflection.Test
{
public class Call_Callvirt_Test
{
[Fact]
public void Call()
{
Func<object, object> func = CreateDelegate(OpCodes.Call);
var result = func.Invoke(new SealedClass());
Assert.Equal(nameof(AbstractClass), result);
}
[Fact]
public void Callvirt()
{
Func<object, object> func = CreateDelegate(OpCodes.Callvirt);
var result = func.Invoke(new SealedClass());
Assert.Equal(nameof(SealedClass), result);
}
public Func<object, object> CreateDelegate(OpCode opCode)
{
Type type = typeof(AbstractClass);
MethodInfo methodInfo = type.GetMethod("GetName");
DynamicMethod dynamicMethod =
new DynamicMethod("invoker_GetName", typeof(object), new Type[] { typeof(object) }, methodInfo.Module, true);
ILGenerator ilGenerator = dynamicMethod.GetILGenerator();
ilGenerator.EmitLoadArg(0);
ilGenerator.Emit(OpCodes.Castclass, type);
ilGenerator.EmitCall(opCode, methodInfo, null);
ilGenerator.Emit(OpCodes.Ret);
return (Func<object, object>) dynamicMethod.CreateDelegate(typeof(Func<object, object>));
}
}
public abstract class AbstractClass
{
public virtual String GetName()
{
return nameof(AbstractClass);
}
}
public sealed class SealedClass : AbstractClass
{
public override String GetName()
{
return nameof(SealedClass);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment