我试图生成一个实现接口的动态类,但其中一个或多个成员已存在于基础中.我在C#中编译了以下代码,并在反射器中检查它以查看C#编译器的功能.
class BaseClass
{
public string Bob
{
get { return "Bob"; }
}
}
interface IStuff
{
string Bob { get; }
}
class SubClass : BaseClass, IStuff
{
}
Run Code Online (Sandbox Code Playgroud)
Reflector没有在SubClass中显示任何实现.
.class private auto ansi beforefieldinit SubClass
extends Enterprise.Services.OperationalActions.Business.Filters.BaseClass
implements Enterprise.Services.OperationalActions.Business.Filters.IStuff
{
}
Run Code Online (Sandbox Code Playgroud)
但是如果我没有明确地发出成员,则TypeBuilder.CreateType()抛出一个InvalidOperationException声明该成员没有实现.所以我的问题是,我如何告诉TypeBuilder接口成员应该从基础实现它的实现?
看起来TypeBuilder你必须添加一个私人pass-thru,只是为了让它快乐(下图).您也可以尝试使用IKVM构建器 - 几乎相同的API,但它可能没有此限制.
using System;
using System.Reflection;
using System.Reflection.Emit;
public class BaseClass
{
public string Bob
{
get { return "Bob"; }
}
}
public interface IStuff
{
string Bob { get; }
}
static class Program
{
static void Main()
{
var name = new AssemblyName("foo");
var asm = AppDomain.CurrentDomain.DefineDynamicAssembly(name, AssemblyBuilderAccess.Run);
var mod = asm.DefineDynamicModule("foo");
var parent = typeof(BaseClass);
var type = mod.DefineType("SubClass", parent.Attributes, parent);
type.AddInterfaceImplementation(typeof(IStuff));
var bob_get = type.DefineMethod("bob_get", MethodAttributes.Virtual | MethodAttributes.Private,
typeof(string), Type.EmptyTypes);
var il = bob_get.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.EmitCall(OpCodes.Callvirt, parent.GetProperty("Bob").GetGetMethod(), null);
il.Emit(OpCodes.Ret);
type.DefineMethodOverride(bob_get, typeof(IStuff).GetProperty("Bob").GetGetMethod());
var final = type.CreateType();
IStuff obj = (IStuff) Activator.CreateInstance(final);
Console.WriteLine(obj.Bob);
}
}
Run Code Online (Sandbox Code Playgroud)
C#编译器实际上会发出不同的代码,BaseType具体取决于您的 SubClass定义是否在同一个程序集中.所以如果你有这个:
interface IStuff
{
string Bob { get; }
}
public class BaseClass
{
public string Bob
{
get { return "Bob"; }
}
}
Run Code Online (Sandbox Code Playgroud)
然后SubClass在另一个C#项目中定义,然后编译器实际上会在其中发出显式接口实现.这是因为在这种情况下,BaseClass.get_Bob将被定义为非虚拟,这意味着它不能用于满足接口的合同.
另请参见为什么C#接口方法未声明为抽象或虚拟?,它在答案的最后明确地讨论了这种奇怪之处.
| 归档时间: |
|
| 查看次数: |
2019 次 |
| 最近记录: |