使用Reflection.Emit实现通用接口

5

我正在使用Reflection.Emit定义一个新类型,我希望这个类型可以实现IComparable(T)接口,其中T将是新定义的类型。

class DefinedType : IComparable<DefinedType>
{
//...
}

对我来说,这似乎是一个先有鸡还是先有蛋的问题。

如果没有办法,我可以实现IComparable接口,但如果可能的话,我更想使用通用接口;只是我无法通过Emit实现,因为在定义类型之前该类型不存在。


希望我有时间去玩这个..但我期待着其他人的回答! - Simon Whitehead
我看到一个方法 addInterfaceImplementation,你可以在构建好一个新类型后,在你的 TypeBuilder 上调用它。难道你不可以使用那个方法事后将 Comparable<YourType> 添加到你的类型中吗? - Jeroen Vannevel
@JeroenVannevel 我认为这是不允许的。我很确定你只能调用 CreateType 一次。 - Anthony
@anthony-arnold:这里是我目前使用Jared的代码所得到的结果,生成了这个编译后的代码。我们已经接近成功,只是类本身现在也包含了一个泛型参数。我还没有找到解决添加泛型参数到类中的方法,因为它需要为接口创建泛型类型。我会继续寻找,但这个中间结果可能会对你有所帮助。 - Jeroen Vannevel
@JeroenVannevel 我觉得我们想太多了。我正在努力解决方案,其中我只有 DefinedTypeBaseclass DefinedType : DefinedTypeBase, IComparable<DefinedTypeBase> - Anthony
@anthony-arnold:这也是可能的,但需要不同的签名..我正在努力创建一种只用作垃圾而不被使用的类型。这样,我就可以在那里定义通用参数,而不会污染实际类型。 - Jeroen Vannevel
2个回答

3
这应该可以运行:
var tb = mb.DefineType("Test", TypeAttributes.Public);
var iface = typeof(IComparable<>).MakeGenericType(tb);
tb.AddInterfaceImplementation(iface);

var meb = tb.DefineMethod("CompareTo", MethodAttributes.Public | MethodAttributes.Virtual, typeof(int), new [] { tb } );
var il = meb.GetILGenerator();
il.ThrowException(typeof(Exception));

var type = tb.CreateType();

幸运的是,TypeBuilder继承自Type,因此您可以在MakeGenericType中使用它。

验证一下,这个是可行的:

var o1 = Activator.CreateInstance(type);
var o2 = Activator.CreateInstance(type);

typeof(IComparable<>).MakeGenericType(o1.GetType()).GetMethod("CompareTo").Invoke(o1, new [] { o2 }).Dump();

您不需要以任何方式将生成的方法绑定到接口,只要它们的签名相同即可。显式接口实现可能会有点棘手,但您不应该需要那样做。


哦,我看到svick的答案已经建议了这个。好吧,这里有一个完整的工作示例,所以请随意接受svick的答案或我的答案,如您所愿 :) - Luaan

2

当调用 MakeGenericType()IComparable<> 转换为 IComparable<DefinedType> 时,您只需将其传递给您的 TypeBuilder 即可。代码可能如下所示:

var boundComparerType = typeof(IComparable<>).MakeGenericType(typeBuilder);
typeBuilder.AddInterfaceImplementation(boundComparerType);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接