Autocaster - .NET 的隐式接口






4.50/5 (12投票s)
2005年1月12日
2分钟阅读

95716

584
.NET 的潜在类型或隐式接口转换的实现。
- 下载 2.0 版本 - 9.44 Kb
- 下载 1.1 版本 - 8.28 Kb (感谢 Emanuele Ruffaldi 移植到 1.1.)
.NET 的潜在类型实现
这个小工具是使用 C# 为 .NET 实现所谓的潜在类型的实验性实现。
什么是潜在类型
在 .NET 中,只有当类型实现公共接口或具有公共基类时,才能以统一的方式处理它们。
当然,所有 .NET 类型都具有公共基类 System.Object
,但如果您想做更多的事情,那么将不同类型视为 System.Object
的用处是有限的。
有时,即使不同的类型没有有意义的公共基类或实现公共接口,您也希望以统一的方式处理它们。
例如,您可能想要将程序中所有具有 Font
类型为 Font
属性的对象存储在一个集合中。 当然,有各种类型具有 Font
属性,但它们并没有太多共同点。 因此,无法将它们强制转换为公共基类型或公共接口。
潜在类型为此问题提供了一个解决方案。 您只需定义一个类似这样的接口
interface IHasFont { Font Font { get; set; } }
您要存储的类型都没有实现此接口,但它们都可以实现它,因为它们具有所需的属性访问器方法。 通常,您只需为每个类型编写一个包装器类,该类实现所需的接口并将实现委托给包装的类。 AutoCaster 使用 System.Reflection.Emit
自动执行此操作。
以下是一个如何使用 AutoCaster 机制的示例
//create various objects that have a Font property, but not much else in common
System.Windows.Forms.Button button1=new Button("Foo");
System.Windows.Forms.ListViewItem listViewItem1=new ListViewItem("Bar");
System.Windows.Forms.FontDialog fontDialog1=new FontDialog();
//store them in a list of IHasFont. This would normally be impossible since
//none of the types supports the IHasFont interface. But since they all implement
//the Font property, we can automatically generate wrappers that do implement
//the IHasFont interface!
List<IHasFont> items=new List<IHasFont>();
items.Add(Latent<IHasFont>.Cast(button1));
items.Add(Latent<IHasFont>.Cast(listViewItem1));
items.Add(Latent<IHasFont>.Cast(fontDialog1));
//change the font for all items in the list
foreach(IHasFont x in items)
x.Font=new Font("Times New Roman",12);
使用潜在类型的危险
潜在类型的问题通常会导致静态和动态类型系统拥护者之间的宗教辩论。 这总结了这场辩论。 显然,我认为在某些情况下,潜在类型是有用的。 但我已经警告过你!
代码
该类使用反射并发出 MSIL 代码,因此您需要各种权限才能运行它。 我诚实地认为,它也是反射和自动发出 MSIL 的一个很好的例子。 我使用原型,因为 Activator.CreateInstance
太慢,无法在每次需要新的包装器实例时使用。
该代码使用了一些 .NET 2.0 功能,例如泛型。 但是,自动包装器生成也应该在 .NET 1.0 和 .NET 1.1 下工作。
该代码使用 System.Reflection.Emit
来创建包装器,因此首次使用包装器会带来严重的性能损失。 但是,一旦生成并 JIT 包装器,调用方法将比动态调用快得多。
许可证
此代码是在 BSD 许可下提供的。 换句话说:想用它做什么就做什么,但如果你弄坏了什么,请不要起诉我 :-)