2

我在运行时使用Reflection.Emit. 最终用户提供基本类型以及新类型应支持的接口。如果接口具有基类型不支持的成员,我创建一个存根方法,该方法调用存储在静态字段上的委托(我只支持具有 15 个或更少参数的非泛型方法,没有 ref 或 out 参数,因为这是我当前的要求。请不要提出此限制的问题。委托采用 baseType 的第一个参数),用户可以在尝试构造类型之前提供该参数。

但是,我想避免为类型可以满足的接口成员创建委托存根。例如

public class Goose
{
     public void Quack()
     {
       // quack implementation details go here.
     }
}

public interface IDuck
{
     void Quack()
}

我希望如果您将这里发送Goosenew[]{typeof(IDuck)}我的构建器,我不会void Quack()为 goose 满足接口创建存根。

接口映射不起作用,因为 Goose 没有实现 IDuck,并且我不能要求新构建的类型进行接口映射,因为TypeBuilder它不支持需要构建的类型。

如何以远程有效的方式解决此问题?我只需要调查公开可见的成员,如果一个类型显式地实现了一个具有相同方法的接口,我可以假设它不应该用作目标。(例如,如果 Goose 已实现void IGoose.Quack(),则不应将其视为 的目标void IDuck.Quack())。(无论如何, BindingFlags.Public | BindingFlags.Instance应该足以过滤掉这些元素)。

4

2 回答 2

0

这实际上是一个以有效方式比较名称和签名的问题MemberInfosToString您可以通过调用MemberInfo来获取包含成员姓名和签名的字符串。此字符串可用于确定两个成员是否是签名等效的。如果将字符串放入 aHashSet中,则比较将非常有效。

ToString.NET 框架在内部使用构建可比较的签名字符串的事实来序列化和反序列化MemberInfo对象,但是,AFAIK,这实际上并没有记录。因此,如果您不想依赖这种未记录的行为,您可以构建自己的签名字符串并进行比较。但是,请注意,一旦考虑到泛型类型参数,这可能会变得非常复杂。

于 2012-10-15T14:22:31.853 回答
0

您应该通过将所有基本类型的公共实现成员反射到哈希集中(MemberInfo 确实实现了 GetHashCode 我不知道它是否可以比较不同类型的成员,您可能需要您的哈希对象来匹配签名类型和名称),然后,当您循环访问新接口的成员时,只有在哈希集中不存在存根代码时才会生成存根代码。

在成员存在之前在 TypeBuilder 上声明接口不是问题,只要您在它们存在之前不调用 CreateType 并且您不应该关心基类型实现的其他接口,因为您只关心签名的成员与您的新界面相匹配。

只要您按接口和基类型缓存结果类型,就性能而言应该不会很差。

于 2011-03-14T15:37:11.120 回答