Delphi 的 .NET 运行时库






4.62/5 (6投票s)
Delphi 的 .NET 运行时库
引言
Delphi 开发人员可以通过 COM 技术访问 .NET 库,这需要进行库注册以及一系列其他工作,才能建立 Delphi 类型库对象与 .NET 库对象类型之间的进程间通信。为 Delphi 中的 .NET 库创建和注册类型库的时代终于结束了。CrystalNet Technologies 推出了 Delphi 的 .NET 运行时库,它提供了一组由 Delphi 编译器通过 COM 调用 CrystalNet 运行时环境行为的底层例程。CrystalNet 运行时环境实现了 .NET 编程语言的执行模型、内置函数和其他基本行为。
主要特点
Delphi 的 .NET 运行时库主要分为两部分:
1. CrystalNet 运行时环境
这是管理 .NET Framework 引擎并实现 Delphi 应用程序和 .NET 库之间进程间通信的系统。运行时环境启动 .NET Framework 引擎,使得用 Delphi 编写的应用程序能够访问 Microsoft Common Object Runtime Library (mscorlib) 中的所有类,或者在无需事先注册库的情况下访问外部库中的所有类。运行时环境的
编程组件是运行时库。
2. CrystalNet Common Object Runtime Library
CrystalNet Common Object Runtime Library (CNCorLib
) 以 C# 和 Delphi 编写。C# CNCorLib
(也称为 CrystalNet
运行时库) 是一个与 CrystalNet
运行时环境紧密耦合的 .NET 程序集。运行时库的 Delphi 部分 (CRLHost
,也称为 Delphi 运行时主机库) 是 CrystalNet
运行时库的一个调度接口实现,它充当 Delphi
与 .NET 进程之间的桥梁。
在 Delphi 中加载 .NET 库
有几种方法可以将 .NET 库加载到运行时主机应用程序域中。可以使用运行时主机 (CorHostManager
) 中定义的加载方法加载库,或者使用运行时主机的 AppDomain
和 AssemblyEx
属性,或者创建 _AppDomain
和 _AssemblyEx
的实例,并使用 load
、LoadFrom
、UnsafeLoadFrom
、ReflectionOnlyLoad
等方法加载 .NET 库。
创建 .NET 库类型的实例
Delphi 运行时库提供了多种方法来创建程序集已加载到运行时主机应用程序域的类型的实例。运行时主机管理器 (CorHostManager
) 有一个属性,用于定义运行时当前应用程序域。该属性称为 AppDomain
。任何加载的程序集都附加到此 AppDomain
,以便可以使用类型名称检索类型或创建属于已加载程序集的类型的实例。如果类型在域中的任何已加载程序集中都不存在,则会触发错误。在 .NET 中,可以使用 Activator
类、AppDomain
类等来创建类型的实例。同样,可以使用 _Activator
接口类型、_AppDomain
接口类型和 CorHostManager AppDomain
属性在 Delphi 中创建 .NET 对象的实例。
注意:使用运行时库在 Delphi 中创建的 .NET 对象的类型为 Olevariant
(可以是 IDispatch
)。
事件处理和回调
.NET Framework 中的事件基于委托模型。事件是对象发送的用于指示操作发生的通知。引发事件的对象称为事件发送者。事件发送者不知道哪个对象或方法将接收 (处理) 其引发的事件。事件通常是事件发送者的成员。.NET Framework 遵循一个命名约定,即所有事件数据类都以 EventArgs
结尾。
标准 .NET Framework 事件 delegate
的示例
public delegate void StateChangeHandler (Object sender, StateChangeEventArgs e);
delegate
是一个包含方法引用的类型。delegate
的声明具有显示其引用的方法的返回类型和参数的签名,并且只能包含与其签名匹配的方法的引用。因此,delegate
等同于 Delphi 中的函数指针或回调。运行时库仅允许 2 个回调方法或函数指针参数。这是在 .NET 中定义事件委托的标准方法。第一个参数是引发事件的发送者,与在 Delphi 中调用事件的实例对象相同。第二个参数是 EventArgs
,它与事件相关的数据,可以通过事件数据类提供。要访问 Delphi 中的事件数据类成员,可以使用 CNObject
接口、反射,或者为 .NET 库中的事件类成员添加 DispId
,并在 Delphi 中创建事件数据类的 DispInterface
类型。会在回调方法中添加 stdcall
调用约定,以确保参数按照从右到左的顺序传递并推送到函数指针或回调方法的参数列表的堆栈中。
以下是上述 .NET 委托的 Delphi 回调方法的示例
假设 C# 中的 StateChangeEventArgs
类具有一个名为 State
的 get
和 set
属性。
示例 1:使用 CNObject
接口访问 StateChangeEventArgs
的事件数据类成员
procedure StateChangeHandler(sender: Olevariant; e : IDispatch); stdcall;
var
oStateValue: Integer;
StateChangeEventArgs: _CNObject;
begin
StateChangeEventArgs := CorHostManager.CastObjectAs(e);
oStateValue:= StateChangeEventArgs.GetPropertyValue('State');
end;
示例 2:使用反射访问 StateChangeEventArgs
的事件数据类成员。
procedure StateChangeHandler(sender: Olevariant; e : IDispatch); stdcall;
var
oStateValue: Integer;
EventArgsType: _Type;
begin
EventArgsType:= CorHostManager.GetType(e);
oStateValue:= EventArgsType.GetProperty('State').GetValue(e);
end;
示例 3:创建 DispInterface
类型以访问 StateChangeEventArgs
的事件数据类成员。
//C# Library StateChangeEventArgs Modification
public class StateChangeEventArgs
{
[DispId(0)]
public int State {get; set ;}
}
//Delphi Corresponding StateChangeEventArgs Dispatch Interface
_StateChangeEventArgs = dispInterface
['{55BF5363-248D-4D10-A8D4-A711BF96DFA6}']
property State : Integer dispId 0;
end;
procedure StateChangeHandler(sender: Olevariant; e: _StateChangeEventArgs); stdcall;
var
oStateValue: Integer;
begin
oStateValue:= e. State;
end;
//OR
procedure StateChangeHandler(sender: Olevariant; e: _IDispatch); stdcall;
var
EventArgs: _StateChangeEventArgs;
oStateValue: Integer;
begin
EventArgs := _StateChangeEventArgs(e);
oStateValue:= EventArgs. State;
end;
有关更多信息以及下载最新的运行时库,请访问 http://sourceforge.net/projects/dotnetruntimelibraryfordelphi/。