您的位置:首页 > 其它

今天的工作不多,想写一个程序管理资金

2005-06-21 00:40 323 查看
毕竟,已经开了头,以前就有过这个想法,已经开了头。今天把数据库需要的基本表格建立起来了,开始做了一个窗体的框架,写了一点需求。
遇到的问题好像以前碰到过,就是说那个处理数据库的层次在什么地方实例化,又是如何与MDI窗体以及子窗体通信的。现在采用的办法是在MDI窗体中初始化那个GenDB在子窗体启动后,将该实例的引用传给它。我不知道是否有更好的办法。
今天这个程序仅仅做了这一点。
晚上继续研究那个反射的文章,看了一点,进展不大:
[接昨天]
显然,这么做不是明智的。对于发现什么类型实现了接口来说,它是一种笨拙的方法,因为它反复每一个类型并要求加载器去加载它。一个更好的办法是,申明所有插件在库被加载的阶段就明确可定位的类型。这可以通过一个程序集级别的用户属性或通过一个配置文件来实现。然而很不幸,无法通过代码加强这种对约定的“查找”(虽然在我的应用中,在运行时如果没有一个满足条件的约定可以抛出一个意外),这样我的应用将不得不依赖一个非常稳固的文档用于它的扩展点,以保证第三方能够正确实现这一部分代码。下面是您如何添加一个程序集级别的用户属性:
[AttributeUsage(AttributeTargets.Assembly)]
public class LogInterfaceTypeAttribute : System.Attribute
{
public readonly string TypeName;
public LogInterfaceTypeAttribute(string typeName)
{
TypeName = typeName;
}
}
[说明,这是一个属性类,关于属性类的用法昨天大概看了一下,没有用过,也搞得不太明白,大意是说属性类,是一个特殊的类,这种类能够用来标明其他的类,好比自定义的Public、Private等,并且可能是能够被反射机制找到?这点我不是很明白。下面看看作者是怎么用的吧。
文档说:指定另一特性类的用法,
文档还说:为运行库编译代码时,该代码被转换为 Microsoft 中间语言 (MSIL),并同编译器生成的元数据一起被放到可移植可执行 (PE) 文件的内部。属性使您得以向元数据中放置额外的描述性信息,并可使用运行库反射服务提取该信息。当您声明从 System.Attribute 派生的特殊类的实例时,编译器创建属性。
文档还说:属性在您编译代码时被发送到元数据中,并可通过运行库反射服务用于公共语言运行库以及任何自定义工具或应用程序。
文档还说:如果要在程序集级别应用属性,请使用 Assembly 关键字。]

LogInterfaceTypeAttribute仅有一个字段,一个字符串的名字,它表明实现了“LogInterface” 接口的类型。在我的应用的文档种,我要求所有的第三方将我的LogInterfaceType属性在程序集的级别加入到他们的库中,这样来告诉我的应用在库中哪些类型实现了我的接口:

[assembly: LogInterfaceType("JoelsLogger")]
class JoelsLogger : LogInterface { ... }
这样,当我加载程序集的时候我就能发现属性:
LogInterfaceType logtype = (LogInterfaceType)asm.GetCustomAttributes(typeof(LogInterfaceType), false)[0]; //获取按类型指定的此程序集的自定义属性。
LogInterface log = (LogInterface)Activator.CreateInstance(asm.GetType(logtype.TypeName));
log.WriteApplicationEvent("Initialized...");
这个方法能够避免前述的那种低效率的循环查找找出实现约定的情形。性能的获得是显著的因为它仅仅加载所需要的第三方得日志库。
引发或者调用一个成员Invoking or Calling a Member
反射的API据其基本目标划分为:引发一个成员和调用检查一个成员。现在,我们来考虑反射背后的实现以便发现到底(性能的)代价出现在哪里。
反射的引发通常需要通过位于反射名称空间中的2种API执行: MethodBase.Invoke 和 Type.InvokeMember。这种引发有时称为“晚期绑定”因为对成员的调用是在运行时分析的而不是在编译时。相对应的由编译器引发的指令调用被称作“早期绑定”。使用晚期绑定执行成员的调用比使用早期绑定的情况要明显慢。为了能揭示这些API性能的内涵,可以在运行时将它们的执行成本(消耗的代价)和使用其他方式调用成员来做一个比较。。图2显示了采用不同机制调用方法的棒图以及每种方法相对应的性能比较。进一步的了解可参考Eric Gunnerson的大作"Calling Code Dynamically"。
这里的衡量是基于一个抽象的情形,只能作为一个基准,因为在实际的情况下,可能会有不同的性能表现。要在您的实际情形下获得精确的度量,办法是测量、测量再测量。
早期绑定和晚期绑定调用
调用机制可被划分为3类:早期绑定、晚期绑定以及混合的早晚期绑定调用。早期绑定调用源自于直接的中间语言(IL)级别的指令(call, callvirt, 和 calli),接口调用和委托调用。这些早期绑定的调用机制典型地由编译器在编译时静态发出,这时编译器能够获得关于被调用目标所需要的所有信息。这些早期绑定的案例明显要比晚期绑定和混合绑定要快,因为(指令)由JIT或者内部代码生成器的编译器会对应较少的X86指令。主动优化也可以由JIT实现,因为调用站点和方法在运行时是不变的而且全部可知。
晚期绑定的例子包括MethodBase.Invoke, 通过Invoke 的DynamicMethod,和Type.InvokeMember,以及晚期绑定委托调用(通过Delegate.DynamicInvoke对委托调用)。相对于早期绑定来说,所有这些方法都会带来明显的负面的性能影响。即便在最好的情况下,它们也要比最慢的早期绑定要慢上一个数量级。Type.InvokeMember是一种最慢的晚期绑定调用机制,因为它需要2个功能才能够正确调用一个成员。首先,它需要通过用户的字符串输入描绘出将要调用的成员,然后执行检查以确保调用的安全。另一方面MethodBase.Invoke不需要描绘出将要调用的方法因为MethodBase已经确定了方法的一致性。
为了进一步探索反射如何建立和调用一个成员,考虑一个MethodBase.Invoke 的典型用法:
[未完待续……]
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐