net runtime library for delphi - sourceforge.net · 4.3.2 generating source code and compiling a...

1460
.Net Runtime Library for Delphi

Upload: dinhhanh

Post on 25-Apr-2019

235 views

Category:

Documents


0 download

TRANSCRIPT

.Net Runtime Library for

Delphi

.Net Runtime Library for Delphi

1

Table of Contents 1. What's New ............................................................................................................................... 4

2. Getting Started .......................................................................................................................... 6

2.1 Overview ............................................................................................................................. 8

2.2 System Requirements ....................................................................................................... 11

2.3 Installation Guide .............................................................................................................. 12

3. How to: .................................................................................................................................... 12

3.1 Host .Net CLR .................................................................................................................... 12

3.2 Use Application Domains .................................................................................................. 14

Describes how to programmatically create an application domain. ......................... 15

Describes how to programmatically unload an application domain. ........................ 15

Provides an introduction to configuring an application domain. .............................. 15

Describes how to retrieve setup information from an application domain. ............. 15

Describes how to load an assembly into an application domain. .............................. 15

Describes how to retrieve information about an assembly. ....................................... 15

Explains how you can receive a notification that an exception has been thrown,

before the common language runtime has begun searching for exception

handlers.............................................................................................................................. 15

Provides guidance on using the AppDomain.AssemblyResolve event to resolve

assembly load failures. ..................................................................................................... 15

Represents an application domain. Provides methods for creating and controlling

application domains. ........................................................................................................ 15

Describes how to create dynamic assemblies. ............................................................. 15

Describes how to use the Reflection class to obtain information about an

assembly. ........................................................................................................................... 15

3.2.1 How to: Create an Application Domain ..................................................................... 16

3.2.2 How to: Unload an Application Domain .................................................................... 17

3.2.3 How to: Configure an Application Domain ................................................................ 20

3.2.4 Retrieving Setup Information from an Application Domain ...................................... 23

3.2.5 How to: Load Assemblies into an Application Domain .............................................. 28

3.2.6 How to: Obtain Type and Member Information from an Assembly .......................... 29

3.2.7 How to: Receive First-Chance Exception Notifications .............................................. 44

3.2.8 Resolving Assembly Loads ......................................................................................... 53

.Net Runtime Library for Delphi

2

3.3 Create Instance of .Net Objects ........................................................................................ 56

3.4 Handling and Raise Events ................................................................................................ 80

3.4.1 Raise and Consume Events ........................................................................................ 85

3.5 Use Base Interface .......................................................................................................... 105

3.6 Use ClrObject Interface ................................................................................................... 107

3.7 Use Array Interfaces........................................................................................................ 143

3.8 Access Static Classes or Static Class Members ............................................................... 163

3.9 Use AsXXXX methods ...................................................................................................... 164

3.10 Use Collections Interfaces ............................................................................................. 165

3.10.1 Non-generic Collections ......................................................................................... 167

3.10.2 Generic Collections ................................................................................................ 192

3.11 Use Linq and Dynamic Linq Interfaces .......................................................................... 226

3.12 Convert Between Types ................................................................................................ 259

Custom Conversions with the ChangeType Method ............................................... 266

3.13 Place .Net Controls on VCL Form .................................................................................. 267

3.14 Format Types ................................................................................................................ 277

3.15 Perform Common I/O Tasks .......................................................................................... 286

3.15.1 How to: Copy Directories ....................................................................................... 288

3.15.2 How to: Enumerate Directories and Files .............................................................. 290

3.15.3 How to: Read and Write to a Newly Created Data File ......................................... 297

3.15.4 How to: Open and Append to a Log File ................................................................ 301

3.15.5 How to: Write Text to a File ................................................................................... 304

3.15.6 How to: Read Text from a File ............................................................................... 307

3.15.7 How to: Read Characters from a String ................................................................. 310

3.15.8 How to: Write Characters to a String ..................................................................... 312

3.15.9 How to: Compress and Extract Files ...................................................................... 315

3.15.10 Composing Streams ............................................................................................. 326

3.16 Globalization ................................................................................................................. 331

3.17 Use WideString instead of String in DispInterfaces ...................................................... 353

4. Dynamic Programming ......................................................................................................... 358

4.1 Reflection ........................................................................................................................ 358

4.1.1 Viewing Type Information ........................................................................................ 360

4.1.2 How to: Examine and Instantiate Generic Types with Reflection ........................... 371

4.1.3 Accessing Custom Attributes ................................................................................... 387

.Net Runtime Library for Delphi

3

4.1.4 How to: Hook Up a Delegate Using Reflection ........................................................ 389

4.1.5 Reflection Using ClrObject ....................................................................................... 406

4.2 Emitting Dynamic Methods and Assemblies .................................................................. 406

4.2.1 How to: Define a Generic Type with Reflection Emit .............................................. 407

4.3 Dynamic Source Code Generation and Compilation ...................................................... 432

4.3.1 Using the CodeDOM ................................................................................................ 432

4.3.2 Generating Source Code and Compiling a Program from a CodeDOM Graph ........ 439

4.3.3 How to: Create a Class Using CodeDOM .................................................................. 444

5. Utilities .................................................................................................................................. 481

5.1 Import .Net Assemblies................................................................................................... 481

5.2 Import WSDL/XML Webservices ..................................................................................... 493

6. Constructor Classes ............................................................................................................... 503

6.1 CoClasses ......................................................................................................................... 505

6.1.1 CreateInstance ......................................................................................................... 508

6.1.2 Wrap ........................................................................................................................ 512

7. Symbol Reference ................................................................................................................. 514

7.1 CrystalNet Class Libraries ................................................................................................ 514

7.1.1 Host Class Library ..................................................................................................... 515

7.1.2 Delphi Framework Class Library ............................................................................. 1367

.Net Runtime Library for Delphi

4

1. What's New This article summarizes key new features and improvements in this version of the .NET Runtime

Library for Delphi. This library was built on the previous version by adding many new fixes and

several new features while remaining a very stable product. The new feature included are:

The CrystalNet Common Langauage Runtime Library implements all c# mscorlib types.

These types are represented as dispatch interfaces. In the previous version only the

classes without the interfaces of the mscorlib types were implemented. The library uses

the interfaces in the mscorlib_tlb.pas file. This caused so many issues and to resolve

them all the types in mscorlib were implemented in the Runtime Library.

Ability to load .Net assemblies and create instances of the .net types of objects using a

new reflection class wrappers such as TClrAppDomain, TClrAssembly and TClrActivator

defined in Runtime Host unit.

Ability to load and build Web Services as assemblies using a new class called TClrWSDL.

Using reflection classes or interfaces you can create instances of the imported

webservices, access it fields, properties and invoke it methods.

A TClrObject class which is a wrapper of the _ClrObject interface has been included in

the Runtime Host unit which provides a flexible general purpose data type. The class

can hold Delphi data type values in the form of OleVariant and .Net Objects. This class

has properties and methods which allows a developer to access the fields, properties ,

methods and events of the .net object which this class holds.

A TClrArray class which is a wrapper of the _Array interface has been included in the

Runtime Host unit which is used to store array of Delphi variant or .net objects types.

Type Conversion has been added to this release to help convert one type of data to

another type. There are wraps and unwraps methods for each interfaces which help to

convert from .net data types to CrystalNet common Language Runtime types and vice

versa respectively.

Introduced Dynamic Linq feature in this release. This unit has interfaces which contains

methods to dynamically generate LINQ queries.

More .Net Types have been added to the .Net Runtime Library. These types are

represented as dispatched interfaces in the Delphi part of the runtime library. There are

2 classifications of these interfaces in the library. These are:

1. CNClrLib.Core.Intf which contains interfaces that represent the types defined in

Microsoft Common Object Runtime Library (Mscorlib).

2. The Delphi Framework Class Library which represent all the types defined in the

.Net Framework Class Library. The following table represents the classification of

the Delphi Framework Class Library and their corresponding .Net Framework

class library namespace.

Delphi Framework Class

Library

.Net Framework Class Library

CNClrLib.CodeDom System.CodeDom Namespaces

CNClrLib.Collections System.Collections Namespaces

CNClrLib.ComponentModel System.ComponentModel Namespaces

.Net Runtime Library for Delphi

5

Delphi Framework Class

Library

.Net Framework Class Library

CNClrLib.Configuration System.Configuration Namespaces

CNClrLib.CSharp Microsoft.CSharp Namespaces

CNClrLib.Data System.Data Namespaces

CNClrLib.Deployment System.Deployment Namespaces

CNClrLib.Device System.Device Namespace

CNClrLib.Diagnostics System.Diagnostics Namespaces

CNClrLib.DirectoryServices System.DirectoryServices Namespaces

CNClrLib.Drawing System.Drawing Namespaces

CNClrLib.Dynamic System.Dynamic Namespace

CNClrLib.DynamicLinq CNCorLibrary.CorDynamicLinq

CNClrLib.EnterpriseServices System.EnterpriseServices Namespaces

CNClrLib.IdentityModel System.IdentityModel Namespaces

CNClrLib.Linq System.Linq Namespaces

CNClrLib.Management System.Management Namespaces

CNClrLib.Media System.Media Namespace

CNClrLib.Messaging System.Messaging Namespaces

CNClrLib.Net System.Net Namespaces

CNClrLib.Numerics System.Numerics Namespace

CNClrLib.Printing System.Printing Namespaces

CNClrLib.Resources System.Resources Namespaces

CNClrLib.Runtime System.Runtime Namespaces

CNClrLib.Security System.Security Namespaces

CNClrLib.ServiceModel System.ServiceModel Namespaces

CNClrLib.ServiceProcess System.ServiceProcess Namespaces

CNClrLib.Speech System.Speech Namespaces

CNClrLib.SqlServer Microsoft.SqlServer Namespace

CNClrLib.System System Namespace

CNClrLib.Text System.Text Namespaces

CNClrLib.Threading System.Threading Namespaces

.Net Runtime Library for Delphi

6

Delphi Framework Class

Library

.Net Framework Class Library

CNClrLib.Timers System.Timers Namespace

CNClrLib.Transactions System.Transactions Namespaces

CNClrLib.VisualBasic Microsoft.VisualBasic Namespaces

CNClrLib.Web System.Web Namespaces

CNClrLib.Win32 Microsoft.Win32 Namespaces

CNClrLib.Windows System.Windows Namespaces

CNClrLib.Xaml System.Xaml Namespaces

CNClrLib.Xml System.Xml Namespaces

For more information about the above .net framework class library namespaces, see .Net

Framwork Class Library .

This article does not provide comprehensive information about each new feature. For general

information about the Runtime Library for Delphi, see Getting Started with the .Net Runtime

Library for Delphi.

For supported platforms, see System Requirements. For download links and installation, see

Installtion Guide .

2. Getting Started Many years ago, in the middle of 90's, Microsoft introduced a new revolutionary programming

technology called COM (Component Object Model). It is used to enable inter-process

communication and dynamic object creation in a large range of programming languages.COM

is a platform-independent, distributed, object-oriented system for creating binary software

components that can interact. Most new windows OS features were implemented using COM.

Most programming languages support COM but most of them are not COM-based.

Now Microsoft has introduced a new revolutionary technology which is more powerful than

COM called .Net. New programming languages such as C#, VB.Net, Visual C++ etc were created

using the .Net technology. More and more new .Net components become available on the

market.

Here is a list of some Win32applications that host .Net runtime:

Borland Delphi 8

Microsoft Visual Studio

C# and VB.Net compilers in .Net framework csc.exe and vbc.exe).

Microsoft SQL Server 2005 host .Net framework to execute stored procedures written in

.Net.

https://msdn.microsoft.com/en-us/library/mt472912(v=vs.110).aspxhttps://msdn.microsoft.com/en-us/library/mt472912(v=vs.110).aspx

.Net Runtime Library for Delphi

7

Microsoft Internet information services (IIS) in part that host ASP.Net, including

aspnet_isapi.dll.

Microsoft Internet Explorer 6.0 in part that host .Net controls.

So it is time to support .Net from other Win32/Win64 languages such as Delphi.

.NET Runtime Library for Delphi

The .Net Runtime Library for Delphi is the best library to work with .Net framework from Delphi.

It is designed to provide a way to interact with applications written in anyone of the .Net

langauges: C#, Visual Basic.Net, Delphi.Net, JScript.Net and others. It includes a large class

library known as Delphi Framework Class Library (DFCL). The DFCL is a dispatched interface

representation of the .Net Framework Class Library (FCL). Programs written for .NET Framework

execute in a software environment known as Common Language Runtime (CLR), an application

virtual machine that provides services such as security, memory management, and exception

handling.

The DFCL provides:

User Interface.

Data Access.

Database Connectivity.

Cryptography.

Numeric Algorithm.

Network Communications.

and many more.

Programmers can produce software by combining pascal source codes with .Net framework and

other .Net libraries.

The .Net Runtime Library for Delphi can:

Create .Net objects from assemblies not registered for COM and loading .Net

assemblies from partial or full assembly name, location and streams

Create and use .Net objects that are not COM visible.

Create .Net objects using parameterized or non-parameterized constructors.

Call Static and non-Static properties/methods/fields of .Net object.

Handle .Net exceptions and get all .Net exception properties including exception type

name, StackTrace etc.

Get information about loaded instance of .Net framework such as memory usage and

size of heap by generation.

Work with .Net events.

and many more.

The Runtime Library will not turn your Delphi into .Net language. All the .Net Framework Class

Library is available in the runtime library as dispatched interfaces.

Related Topics

.Net Runtime Library for Delphi

8

Title Description

Overview of the .Net Runtime Library

for Delphi

Provides detailed information for developers who build delphi applications that target the .NET

Framework.

.Net Runtime Library for Delphi System

Requirements

Lists the hardware and software requirements for running the .NET Framework.

Installing the .Net Runtime Library for

Delphi

Provides information about installing the .NET Runtime Library for Delphi.

2.1 Overview The .NET Framework is a new computing platform that simplifies application development in

the highly distributed environment of the Internet. The .NET Framework is designed to fulfill the

following objectives:

To provide a consistent object-oriented programming environment whether object

code is stored and executed locally, executed locally but Internet-distributed, or

executed remotely.

To provide a code-execution environment that minimizes software deployment and

versioning conflicts.

To provide a code-execution environment that guarantees safe execution of code,

including code created by an unknown or semi-trusted third party.

To provide a code-execution environment that eliminates the performance problems of

scripted or interpreted environments.

To make the developer experience consistent across widely varying types of

applications, such as Windows-based applications and Web-based applications.

To build all communication on industry standards to ensure that code based on the

.NET Framework can integrate with any other code.

The .NET Framework has two main components: the common language runtime and the .NET

Framework class library. The common language runtime is the foundation of the .NET

Framework. You can think of the runtime as an agent that manages code at execution time,

providing core services such as memory management, thread management, and remoting,

while also enforcing strict type safety and other forms of code accuracy that ensure security and

robustness. In fact, the concept of code management is a fundamental principle of the runtime.

Code that targets the runtime is known as managed code, while code that does not target the

runtime is known as unmanaged code. The class library, the other main component of the .NET

Framework, is a comprehensive, object-oriented collection of reusable types that you can use to

develop applications ranging from traditional command-line or graphical user interface (GUI)

applications to applications based on the latest innovations provided by ASP.NET, such as Web

Forms and XML Web services.

The .NET Framework can be hosted by unmanaged components that load the common

language runtime into their processes and initiate the execution of managed code, thereby

creating a software environment that can exploit both managed and unmanaged features. The

.Net Runtime Library for Delphi

9

.NET Framework not only provides several runtime hosts, but also supports the development of

third-party runtime hosts.

For example, ASP.NET hosts the runtime to provide a scalable, server-side environment for

managed code. ASP.NET works directly with the runtime to enable ASP.NET applications and

XML Web services, both of which are discussed later in this topic.

Internet Explorer is an example of an unmanaged application that hosts the runtime (in the

form of a MIME type extension). Using Internet Explorer to host the runtime enables you to

embed managed components or Windows Forms controls in HTML documents. Hosting the

runtime in this way makes managed mobile code (similar to Microsoft ActiveX controls)

possible, but with significant improvements that only managed code can offer, such as semi-

trusted execution and secure isolated file storage.

The following illustration shows the relationship of the common language runtime and the class

library to your applications and to the overall system. The illustration also shows how managed

code operates within a larger architecture.

.NET Framework in context

The following sections describe the main components and features of the .NET Framework in

greater detail.

.Net Runtime Library for Delphi

10

Features of the Common Language Runtime

The common language runtime manages memory, thread execution, code execution, code

safety verification, compilation, and other system services. These features are intrinsic to the

managed code that runs on the common language runtime.

With regards to security, managed components are awarded varying degrees of trust,

depending on a number of factors that include their origin (such as the Internet, enterprise

network, or local computer). This means that a managed component might or might not be

able to perform file-access operations, registry-access operations, or other sensitive functions,

even if it is being used in the same active application.

The runtime enforces code access security. For example, users can trust that an executable

embedded in a Web page can play an animation on screen or sing a song, but cannot access

their personal data, file system, or network. The security features of the runtime thus enable

legitimate Internet-deployed software to be exceptionally feature rich.

The runtime also enforces code robustness by implementing a strict type-and-code-verification

infrastructure called the common type system (CTS). The CTS ensures that all managed code is

self-describing. The various Microsoft and third-party language compilers generate managed

code that conforms to the CTS. This means that managed code can consume other managed

types and instances, while strictly enforcing type fidelity and type safety.

In addition, the managed environment of the runtime eliminates many common software

issues. For example, the runtime automatically handles object layout and manages references to

objects, releasing them when they are no longer being used. This automatic memory

management resolves the two most common application errors, memory leaks and invalid

memory references.

The runtime also accelerates developer productivity. For example, programmers can write

applications in their development language of choice, yet take full advantage of the runtime,

the class library, and components written in other languages by other developers. Any compiler

vendor who chooses to target the runtime can do so. Language compilers that target the .NET

Framework make the features of the .NET Framework available to existing code written in that

language, greatly easing the migration process for existing applications.

While the runtime is designed for the software of the future, it also supports software of today

and yesterday. Interoperability between managed and unmanaged code enables developers to

continue to use necessary COM components and DLLs.

The runtime is designed to enhance performance. Although the common language runtime

provides many standard runtime services, managed code is never interpreted. A feature called

just-in-time (JIT) compiling enables all managed code to run in the native machine language of

the system on which it is executing. Meanwhile, the memory manager removes the possibilities

of fragmented memory and increases memory locality-of-reference to further increase

performance.

.Net Runtime Library for Delphi

11

Finally, the runtime can be hosted by high-performance, server-side applications, such as

Microsoft SQL ServerT and Internet Information Services (IIS). This infrastructure enables you

to use managed code to write your business logic, while still enjoying the superior performance

of the industry's best enterprise servers that support runtime hosting.

CrystalNet Class Library

The CrystalNet Class Library is a collection of prewritten classes and interfaces which is used to

start and host the .Net Common Language Runtime as well as interfaces which are wrappers of

the .Net Framework Class Library, any of which can be specified and used by a programmer

when developing an application program. The programmer specifies which classes are being

used and furnishes data that instantiate s each class as an object that can be called when the

program is executed. Access to and use of a class library greatly simplifies the job of the

programmer since standard, pretested code is available that the programmer doesn't have to

write.

See Also

.NET Runtime Library for Delphi System Requirements

Installing the .NET Runtime Library for Delphi

Delphi Framework Class Library

2.2 System Requirements This section provides the requirements, platforms and operating system for the .Net Runtime

Library for Delphi.

For download information and links, see Installing the .Net Runtime Library for Delphi.

Platforms

.Net Framework 4.5.2 or higher version.

The .NET Runtime Library for Delphi requires a privileges in order to install. If you do

not have administrator rights to the computer on which you would like to

install the .NET Runtime Library for Delphi, contact your network administrator.

Supported Delphi Versions

Embarcadero Delphi 2009

Embarcadero Delphi 2010

Embarcadero Delphi XE Or Higher Versions

Supported client operating systems

Microsoft Windows

!!SYMREF.html

.Net Runtime Library for Delphi

12

2.3 Installation Guide .NET is an integral part of many applications running on Windows and provides common functionality for those

applications to run. For delphi developers, the .NET Runtime Library provides a comprehensive and consistent

programming for building integrated Delphi and .Net applications that have visually stunning user experiences and

seamless and secure communication.

Description

To install the Runtime Library on Windows, download the runtime library installation files (32bit

or 64bit) from the download page.

Note

This documentation also includes code examples that you can copy directly from topics and

paste into your own projects.

3. How to: This section describes how to use the Delphi Framework Library.

3.1 Host .Net CLR Before any managed code can be executed, the host must load and initialize the common

language runtime. If your delphi applications utilises the .Net runtime library for delphi, the

Common Language Runtime (CLR) will be started automatically by implicitly creating an

instance of the TClrHost class. To manually start the CLR, call ClrHostManager function or

explicitly create an instance of TClrHost object or call the static function GetDefault of the

TClrHost class. The CLR host class are defined in the CNClrLib.Host namespace . The runtime

host loads the runtime into a process, creates application domains within the process, and loads

and executes user code within those application domains. The purpose of this class is to start

the .net runtime library for delphi which in turn starts the .Net framework CLR and execute

managed codes from delphi. Application domains provide greater reliability by isolating

assemblies from one another. Assemblies can be unloaded from the process by unloading

application domains. The application domain is called TClrAppDomain which is a wrapper of the

AppDomain interface. This class is also defined in the CNClrLib.Host namespace .

Example

Pascal

program CreateCLRHostDemo;

{$APPTYPE CONSOLE}

{$R *.res}

http://www.crystalnet-tech.com/RuntimeLibrary/Download.aspx

.Net Runtime Library for Delphi

13

uses

System.SysUtils,

CNClrLib.Host,

CNClrLib.Core,

CNClrLib.Enums;

var

Console: _Console;

ClrHost: TClrHost;

begin

try

//Calling any of the following lines of code will start the .net

runtime host.

//NB: The CLRHost instance is created once and any attempt to

recreate the instance explicitly

// will cause an error.

//1.

//Calling this method will create an instance of the TClrHost

class implicitly

//and start the runtime host if the host object has not been

created already.

Console := CoConsole.CreateInstance;

//2.

//Calling this global function in the CNClrLib.Host namespace

will use the default

//TClrHost instance created. If the instance has not been

created already, the function

//automatically create a new instance of the TClrHost class.

ClrHost := ClrHostManager;

//3.

//To Explicitly Create an instance of the host class, either

call the static

.Net Runtime Library for Delphi

14

//method GetDefault or the Create constructor of the TClrHost

Class.

//a. Using GetDefault

ClrHost := TClrHost.GetDefault;

//b. Using Create Constructor

ClrHost := TClrHost.Create;

except

on E: Exception do

Writeln(E.ClassName, ': ', E.Message);

end;

end.

3.2 Use Application Domains Application domains provide a flexible and secure method of isolating running applications.Application domains are

usually created and manipulated by run-time hosts. Occasionally, you may want your application to programmatically

interact with your application domains, for example, to unload a component without having to stop your application

from running.Application domains aid security, separating applications from each other and each other's data. A single

process can run several application domains, with the same level of isolation that would exist in separate processes.

Running multiple applications within a single process increases server scalability.

In the following code example, you create a new application domain and then load and execute a previously built

assembly, HelloWorld.exe, that is stored on drive C.

Delphi

var

newDomain: TClrAppDomain;

begin

// Create the application domain.

newDomain := TClrAppDomain.CreateDomain('NewApplicationDomain');

// Load and execute an .Net assembly:

newDomain.ExecuteAssembly('c:\HelloWorld.exe');

// Unload the application domain:

TClrAppDomain.Unload(newDomain);

end.

.Net Runtime Library for Delphi

15

Application Domains Overview

Application domains have the following properties:

An assembly must be loaded into an application domain before it can be executed.

Faults in one application domain cannot affect other code running in another application domain.

Individual applications can be stopped and code unloaded without stopping the entire process. You cannot unload individual assemblies or types, only entire application domains.

In This Section

How to: Create an Application Domain

Describes how to programmatically create an application domain.

How to: Unload an Application Domain

Describes how to programmatically unload an application domain.

How to: Configure an Application Domain

Provides an introduction to configuring an application domain.

Retrieving Setup Information from an Application Domain

Describes how to retrieve setup information from an application domain.

How to: Load Assemblies into an Application Domain

Describes how to load an assembly into an application domain.

How to: Obtain Type and Member Information from an

Assembly

Describes how to retrieve information about an assembly.

How to: Receive First-Chance Exception Notifications

Explains how you can receive a notification that an exception has been thrown, before the common language

runtime has begun searching for exception handlers.

Resolving Assembly Loads

Provides guidance on using the AppDomain.AssemblyResolve event to resolve assembly load failures.

Reference

AppDomain/TClrAppDomain

Represents an application domain. Provides methods for creating and controlling application domains.

Related Sections

Emitting Dynamic Methods and Assemblies

Describes how to create dynamic assemblies.

Reflection Overview

Describes how to use the Reflection class to obtain information about an assembly.

CNClrLib_Core_Intf__AppDomain.html

.Net Runtime Library for Delphi

16

3.2.1 How to: Create an Application Domain The common language runtime host creates application domains automatically when they are needed. However, you

can create your own application domains and load into them those assemblies that you want to manage personally.

You can also create application domains from which you execute code. You create a new application domain using one

of the overloaded CreateDomain methods in the AppDomain interface TClrAppDomain class. You can give the

application domain a name and reference it by that name.

The following example creates a new application domain, assigns it the name MyDomain, and then prints the name of

the host domain and the newly created child application domain to the console.

Example

Delphi

program AppDomain1;

{$APPTYPE CONSOLE}

{$R *.res}

uses

System.SysUtils,

CNClrLib.Host,

CNClrLib.Core;

var

Console: _Console;

domain: TClrAppDomain;

begin

try

Console := CoConsole.CreateInstance;

try

Console.WriteLine_14('Creating new

AppDomain.');

CNClrLib_Core_Intf__AppDomain.html

.Net Runtime Library for Delphi

17

domain :=

TClrAppDomain.CreateDomain('MyDomain');

Console.WriteLine_14('Host domain: ' +

TClrAppDomain.GetCurrentDomain.FriendlyName);

Console.WriteLine_14('child domain: ' +

domain.FriendlyName);

Console.ReadKey;

finally

Console := nil;

end;

except

on E: Exception do

Writeln(E.ClassName, ': ', E.Message);

end;

end.

3.2.2 How to: Unload an Application Domain When you have finished using an application domain, unload it using the TClrAppDomain.Unload method. The Unload

method gracefully shuts down the specified application domain. During the unloading process, no new threads can

access the application domain, and all application domain-specific data structures are freed. Assemblies loaded into the

application domain are removed and are no longer available. If an assembly in the application domain is domain-

neutral, data for the assembly remains in memory until the entire process is shut down. There are situations where the

request to unload an application domain does not work and results in a CannotUnloadAppDomainException .

The following example creates a new application domain called MyDomain, prints some information to the console, and

then unloads the application domain. Note that the code then attempts to print the friendly name of the unloaded

application domain to the console. This action generates an exception that is handled by the try/catch statements at the

end of the program.

Example

Delphi

program AppDomain;

CNClrLib_Core_Intf__CannotUnloadAppDomainException.html

.Net Runtime Library for Delphi

18

{$APPTYPE CONSOLE}

{$R *.res}

uses

System.SysUtils,

CNClrLib.Host,

CNClrLib.Core,

System.Win.ComObj;

var

Console: _Console;

domain: TClrAppDomain;

AppDomainUnloadedException:

_AppDomainUnloadedException;

begin

Console := CoConsole.CreateInstance;

try

Console.WriteLine_14('Creating new

AppDomain.');

domain :=

TClrAppDomain.CreateDomain('MyDomain', nil);

Console.WriteLine_14('Host domain: ' +

TClrAppDomain.GetCurrentDomain.FriendlyName);

Console.WriteLine_14('child domain: ' +

domain.FriendlyName);

.Net Runtime Library for Delphi

19

TClrAppDomain.Unload(domain);

Console.WriteLine();

Console.WriteLine_14('Host domain: ' +

TClrAppDomain.GetCurrentDomain.FriendlyName);

// The following statement creates an

exception because the domain no longer exists.

Console.WriteLine_14('child domain: ' +

domain.FriendlyName);

except

on E: EOleException do

begin

AppDomainUnloadedException :=

CoAppDomainUnloadedException.Wrap(EClrException.Ge

tExceptionIntf(E.ErrorCode));

Console.WriteLine_14(AppDomainUnloadedException.Ge

tType().FullName);

Console.WriteLine_14('The appdomain MyDomain

does not exist.');

end;

on E: Exception do

Writeln(E.ClassName, ': ', E.Message);

end;

Console.ReadKey;

end.

.Net Runtime Library for Delphi

20

//Output

//Creating new AppDomain.

//Host domain: DefaultDomain

//child domain: MyDomain

//

//Host domain: DefaultDomain

//System.AppDomainUnloadedException

//The appdomain MyDomain does not exist.

3.2.3 How to: Configure an Application

Domain You can provide the common language runtime with configuration information for a new application domain using the

AppDomainSetup interface. When creating your own application domains, the most important property is

ApplicationBase. The other AppDomainSetup properties are used mainly by runtime hosts to configure a particular

application domain. The ApplicationBase property defines the root directory of the application. When the runtime

needs to satisfy a type request, it probes for the assembly containing the type in the directory specified by the

ApplicationBase property.

The following example creates an instance of the AppDomainSetup class, uses this class to create a new application

domain, writes the information to console, and then unloads the application domain.

Example

Delphi

program AppDomain;

{$APPTYPE CONSOLE}

{$R *.res}

uses

System.SysUtils,

CNClrLib.Host,

CNClrLib_Core_Intf__AppDomainSetup.html

.Net Runtime Library for Delphi

21

CNClrLib.Core;

var

Console: _Console;

domain: TClrAppDomain;

domaininfo: _AppDomainSetup;

begin

try

Console := CoConsole.CreateInstance;

// Create application domain setup

information.

domaininfo := CoAppDomainSetup.CreateInstance;

domaininfo.ApplicationBase :=

'C:\Temp\AppDomainDemo\EXE\Win32\Debug';

// Create the application domain.

domain :=

TClrAppDomain.CreateDomain('MyDomain', nil,

domaininfo);

// Write application domain information to the

console.

Console.WriteLine_14('Host domain: ' +

TClrAppDomain.GetCurrentDomain.FriendlyName);

Console.WriteLine_14('child domain: ' +

domain.FriendlyName);

.Net Runtime Library for Delphi

22

Console.WriteLine_14('Application base is: ' +

domain.DefaultInterface.SetupInformation.Applicati

onBase);

//NB: The DefaultInterface is the AppDomain

Inteface. The TClrAppDomain is

//a wrapper of the _AppDomain Dispatch

Interface

// Unload the application domain.

TClrAppDomain.Unload(domain);

Console.ReadKey;

except

on E: Exception do

Writeln(E.ClassName, ': ', E.Message);

end;

end.

//Output

//Host domain: DefaultDomain

//child domain: MyDomain

//Application base is:

C:\Temp\AppDomainDemo\EXE\Win32\Debug

.Net Runtime Library for Delphi

23

3.2.4 Retrieving Setup Information from an

Application Domain Each instance of an application domain consists of both properties and AppDomainSetup information. You can retrieve

setup information from an application domain using the wrapper class TClrAppDomain or AppDomain interface. This

class or interface provides several members that retrieve configuration information about an application domain. You

can also query the AppDomainSetup object for the application domain to obtain setup information that was passed to

the domain when it was created.

The following example creates a new application domain and then prints several member values to the console.

Delphi

program AppDomain;

{$APPTYPE CONSOLE}

{$R *.res}

uses

System.SysUtils,

CNClrLib.Host,

CNClrLib.Core;

var

Console: _Console;

domain: TClrAppDomain;

begin

try

Console := CoConsole.CreateInstance;

// Create the application domain.

domain := TClrAppDomain.CreateDomain('MyDomain', nil);

// Write application domain information to the console.

Console.WriteLine_14('Host domain: ' +

TClrAppDomain.GetCurrentDomain.FriendlyName);

Console.WriteLine_14('New domain: ' + domain.FriendlyName);

Console.WriteLine_14('Application base is: ' +

domain.BaseDirectory);

Console.WriteLine_14('Relative search path is: ' +

domain.DefaultInterface.RelativeSearchPath);

CNClrLib_Core_Intf__AppDomainSetup.htmlCNClrLib_Core_Intf__AppDomain.html

.Net Runtime Library for Delphi

24

Console.WriteLine_15('Shadow copy files is set to: {0}',

domain.DefaultInterface.ShadowCopyFiles);

//NB: The DefaultInterface is the AppDomain Inteface. The

TClrAppDomain is

//a wrapper of the _AppDomain Dispatch Interface

// Unload the application domain.

TClrAppDomain.Unload(domain);

Console.ReadKey;

except

on E: Exception do

Writeln(E.ClassName, ': ', E.Message);

end;

end.

//Output

//Host domain: DefaultDomain

//New domain: MyDomain

//Application base is: C:\Temp\AppDomainDemo\EXE\Win32\Debug\

//Relative search path is:

//Shadow copy files is set to: False

.Net Runtime Library for Delphi

25

.Net Runtime Library for Delphi

26

The following example sets, and then retrieves, setup information for an application domain. Note that

AppDomain.SetupInformation.ApplicationBase gets the configuration information.

Delphi

program AppDomain;

{$APPTYPE CONSOLE}

{$R *.res}

uses

System.SysUtils,

CNClrLib.Host,

CNClrLib.Core;

var

Console: _Console;

domain: TClrAppDomain;

domaininfo: _AppDomainSetup;

begin

try

Console := CoConsole.CreateInstance;

// Create application domain setup information.

domaininfo := CoAppDomainSetup.CreateInstance;

domaininfo.ApplicationBase :=

'C:\Temp\AppDomainDemo\EXE\Win32\Debug\';

domaininfo.ConfigurationFile :=

'C:\Temp\AppDomainDemo\EXE\Win32\Debug\AppDomain.exe.Config';

.Net Runtime Library for Delphi

27

// Create the application domain.

domain := TClrAppDomain.CreateDomain('MyDomain', nil, domaininfo);

// Write application domain information to the console.

Console.WriteLine_14('Host domain: ' +

TClrAppDomain.GetCurrentDomain.FriendlyName);

Console.WriteLine_14('child domain: ' + domain.FriendlyName);

Console.WriteLine();

Console.WriteLine_14('Application base is: ' +

domain.DefaultInterface.SetupInformation.ApplicationBase);

Console.WriteLine_14('Configuration file is: ' +

domain.DefaultInterface.SetupInformation.ConfigurationFile);

//NB: The DefaultInterface is the AppDomain Inteface. The

TClrAppDomain is

//a wrapper of the _AppDomain Dispatch Interface

// Unload the application domain.

TClrAppDomain.Unload(domain);

Console.ReadKey;

except

on E: Exception do

Writeln(E.ClassName, ': ', E.Message);

end;

end.

//Output

//Host domain: DefaultDomain

//child domain: MyDomain

//

//Application base is: C:\Temp\AppDomainDemo\EXE\Win32\Debug\

//Configuration file is:

C:\Temp\AppDomainDemo\EXE\Win32\Debug\AppDomain.exe.Config

.Net Runtime Library for Delphi

28

3.2.5 How to: Load Assemblies into an

Application Domain There are several ways to load an assembly into an application domain. These are:

The LoadFrom method of the TClrAssembly class loads an assembly given its file location. Loading assemblies with this method uses a different load context.

The ReflectionOnlyLoad and ReflectionOnlyLoadFrom methods load an assembly into the reflection-only context. Assemblies loaded into this context can be examined but not executed, allowing the examination of

assemblies that target other platforms. See How to: Load Assemblies into the Reflection-Only Context.

Methods such as CreateInstance of the TClrAppDomain class can load assemblies into an application domain.

The GetType method of the Type interface can load assemblies.

The Load method of the TClrAppDomain class can load assemblies, but is primarily used for COM interoperability. It should not be used to load assemblies into an application domain other than the

application domain from which it is called.

Example

The following code loads an assembly named "example.exe" or "example.dll" into the current application domain, gets a

type named Example from the assembly, gets a parameterless method named MethodA for that type, and executes the

method. For a complete discussion on obtaining information from a loaded assembly, see Dynamically Loading and

Using Types.

Delphi

program Asmload0;

{$APPTYPE CONSOLE}

{$R *.res}

uses

System.SysUtils,

CNClrLib.Host,

CNClrLib.Core;

var

AAsm: TClrAssembly;

myType: _Type;

myMethod: _MethodInfo;

obj: OleVariant;

Clrobj: _ClrObject;

begin

How_to__Load_Assemblies_into_the_Reflection-Only_Context.htmlCNClrLib_Core_Intf__Type.htmlDynamically_Loading_and_Using_Types.htmlDynamically_Loading_and_Using_Types.html

.Net Runtime Library for Delphi

29

// Use the file name to load the assembly into the current

// application domain.

AAsm := TClrAssembly.Load('example');

// Get the type to use.

myType := TClrAssembly.GetType('Example');

// Get the method to call.

myMethod := myType.GetMethod_5('MethodA');

// Create an instance.

obj := TClrActivator.CreateInstance(myType);

// Execute the method.

myMethod.Invoke_2(obj, nil);

//OR

//You can use the ClrObject to invoke the method

// Create an instance of ClrObject.

Clrobj := TClrActivator.ClrCreateInstance(myType);

// Execute the method.

Clrobj.InvokeMethod('MethodA');

end.

3.2.6 How to: Obtain Type and Member

Information from an Assembly The CNClrLib.Core.Intf namespace contains many methods for obtaining information from an assembly. This section

demonstrates one of these methods. For additional information, see Reflection Overview.

The following example obtains type and member information from an assembly.

Example

Delphi

CNClrLib_Core_Intf.html

.Net Runtime Library for Delphi

30

program Asminfo1;

{$APPTYPE CONSOLE}

{$R *.res}

uses

System.SysUtils,

CNClrLib.Host,

CNClrLib.Core,

CNClrLib.Enums;

var

Console: _Console;

myType: _Type;

I: Integer;

MemberInfoArray: _MemberInfoArray;

begin

Console := CoConsole.CreateInstance;

Console.WriteLine_14('Reflection.MemberInfo');

// Get the Type and MemberInfo.

// Insert the fully qualified class name inside the quotation marks

in the

// following statement.

myType := TClrAssembly.GetType('System.IO.BinaryReader');

MemberInfoArray := myType.GetMembers_1(BindingFlags_Public or

BindingFlags_NonPublic or BindingFlags_Static or

BindingFlags_Instance or BindingFlags_DeclaredOnly);

// Get and display the DeclaringType method.

.Net Runtime Library for Delphi

31

Console.WriteLine_15('There are {0} documentable members in ',

MemberInfoArray.Length);

Console.WriteLine_15('{0}.', myType.FullName);

for I := 0 to MemberInfoArray.Length - 1 do

Console.WriteLine_14(MemberInfoArray[I].Name);

Console.ReadKey;

end.

//Output

//Reflection.MemberInfo

//There are 43 documentable members in

//System.IO.BinaryReader.

//get_BaseStream

//Close

//Dispose

//Dispose

//PeekChar

//Read

//ReadBoolean

//ReadByte

//ReadSByte

//ReadChar

//ReadInt16

//ReadUInt16

//ReadInt32

//ReadUInt32

//ReadInt64

//ReadUInt64

//ReadSingle

//ReadDouble

.Net Runtime Library for Delphi

32

//ReadDecimal

//ReadString

//Read

//InternalReadChars

//InternalReadOneChar

//ReadChars

//Read

//ReadBytes

//FillBuffer

//Read7BitEncodedInt

//.ctor

//.ctor

//.ctor

//BaseStream

//m_stream

//m_buffer

//m_decoder

//m_charBytes

//m_singleChar

//m_charBuffer

//m_maxCharsSize

//m_2BytesPerChar

//m_isMemoryStream

//m_leaveOpen

//MaxCharBytesSize

.Net Runtime Library for Delphi

33

.Net Runtime Library for Delphi

34

.Net Runtime Library for Delphi

35

Accessing external .Net Library Type Objects

Unlike COM in Delphi which requires the .Net library classes to be

marked with ComVisible attribute or the .Net Assembly to be marked as

ComVisible and the .Net Library types to be registered, the .Net Runtime

Library for Delphi behaves differently. Even though the same COM

mechanism is used, it does not require marking the .Net classes or the

assembly with ComVisible and no registration of the .Net library types

are required. In order to access any external .Net library objects; firstly,

the external library has to be loaded onto the runtime host AppDomain

using the Load Assembly methods in the runtime host class or other

means described in Section 3 above. Secondly, create an instance of the

.Net type using the CreateInstance methods in the runtime host class or

other means described in Section 4 above. Once the instance has been

created successfully, there are 3 possible ways to access the methods

and properties and perhaps the public fields of the object instance

created. These are; using CNObject interface, using Reflection and using

COM Dispatch Interface. There are three ways to access members of .net

types: These are:

Using ClrObject Interface

Using Reflection Interfaces

.Net Runtime Library for Delphi

36

Using COM Dispatch

Using ClrObject Interface

Common Language Runtime Object (ClrObject) interface or the wrapper

class TClrObject has methods which allow you to retrieve and update

object type field values, property values or invoke methods of the object

type.

For more information, see Use ClrObject Interface .

Example in C#

C#

public Object this[Int32 index]

{

Get {...}

Set {...}

}

public bool IsData

{

Get {...}

Set {...}

}

public void GetData()

{

....

}

public void GetData(bool Accept)

{

....

}

.Net Runtime Library for Delphi

37

To access the above properties and methods in delphi using ClrObject interface, see the

example code below;

Delphi

var

clrObject: TClrObject;

Index0: OleVariant;

IsData: Boolean;

begin

//Assuming the TClrObject instance has been created

//Access the property indexer at position 0

Index0 := clrObject.GetPropertyValue('Item', 0);

//Or

.Net Runtime Library for Delphi

38

Index0 := clrObject.GetPropertyValue('Item', 'System.Int32', 0);

//Access the property IsData

IsData := clrObject.GetPropertyValue('IsData');

//Set True to the property IsData

clrObject.SetPropertyValue('IsData', True);

//Invoke the parameterless method GetData

clrObject.InvokeMethod('GetData');

//Invoke the method GetData with parameter

clrObject.InvokeMethod('GetData', 'System.Boolean', [True]);

end;

.Net Runtime Library for Delphi

39

Using Reflection Interfaces

Reflection is the ability of a code to read its own metadata for the purpose of finding

assemblies, modules and type information at runtime. In other words, reflection provides

objects that encapsulate assemblies, modules and types. A program reflects on itself by

extracting metadata from its assembly and using that metadata either to inform the user or to

modify its own behaviour. By using Reflection with the help of the Delphi Framework Library,

one is able to find out details of an object, method, and create objects and invoke methods at

runtime. The CNClrLib.Core.Intf namespace contains interfaces that provide a managed view of

loaded types, methods, and fields, with the ability to dynamically create and invoke types. For

more information, see Dynamic Programming using Reflection .

Example

Delphi

program Example;

{$APPTYPE CONSOLE}

{$R *.res}

uses

System.SysUtils,

CNClrLib.Host,

CNClrLib.Core;

var

Console: _Console;

ASQLCon: OleVariant;

ASQLConStr: WideString;

ASQLConType: _Type;

AConnProp: _PropertyInfo;

AOpenMeth,

ACloseMeth: _MethodInfo;

begin

Console := CoConsole.CreateInstance;

try

//Load Assembly by Partial Name(This load the assembly from the

GAC)

Console.WriteLine_14('Load System.Data Assembly from the GAC.

FileName: System.Data.dll');

TClrAssembly.LoadWithPartialName('System.Data');

//Create Instance of System.Data.SqlClient.SqlConnection Type

ASQLCon :=

TClrActivator.CreateInstance('System.Data.SqlClient.SqlConnection');

ASQLConStr := 'Data Source=myServerAddress;Initial Catalog=

myDataBase;UserID=myUsername;Password=myPassword';

Console.WriteLine_15('Connecting to : {0}', ASQLConStr);

ASQLConType := TClrAssembly.GetObjectType(ASQLCon);

AConnProp := ASQLConType.GetProperty_6('ConnectionString');

AConnProp.SetValue_2(ASQLCon, ASQLConStr);

AOpenMeth := ASQLConType.GetMethod_5('Open');

AOpenMeth.Invoke_2(ASQLCon, nil);

Console.WriteLine_14('Connection Opened');

CNClrLib_Core_Intf.html

.Net Runtime Library for Delphi

40

ACloseMeth := ASQLConType.GetMethod_5('Close');

ACloseMeth.Invoke_2(ASQLCon, nil);

Console.WriteLine_14('Connection Closed');

except

on E: Exception do

Console.WriteLine_15('Exception: {0}', E.Message);

end;

end.

.Net Runtime Library for Delphi

41

Using COM Dispatch

This approach is the easiest and more flexible way of accessing external .Net library types by

generating the class types in .Net library as a DispInterface type with user defined DispId. DispId

is very important when using this approach to access methods and properties of the .Net

external library types. Using the COM DispInterface, the coder does not need to register the .net

libraries; however the .Net Class methods and properties should be marked with DispId

attributes. You can either mark the .Net Class with ComVisible attribute and subsequently use

the Type Library importer in Delphi to generate Delphi library version of the .Net Library or you

can manually code a corresponding DispInterface type in Delphi making sure that the DispIds in

the properties and methods of the .Net library is the same as the DispIds in the properties and

methods of the corresponding Delphi DispInterface type. Form more information, See Access

External .Net Types using COM Dispatch.

Assuming the following class is compiled into a Mathematics.dll in c#

C#

using System.Runtime.InteropServices;

namespace Mathematics

Access_External_.Net_Types_using_COM_Dispatch.htmAccess_External_.Net_Types_using_COM_Dispatch.htm

.Net Runtime Library for Delphi

42

{

public class Mathematics

{

[DispId(0)]

public int Add(int a, int b)

{

return a + b;

}

[DispId(1)]

public int Subtract(int a, int b)

{

return a - b;

}

[DispId(2)]

public bool Equal(int a, int b)

{

return a == b;

}

}

}

.Net Runtime Library for Delphi

43

You can create a corresponding dispatch interface of the c# mathematics class in the

Mathematics.dll as follows:

Delphi

_Mathematics = dispinterface

['{D77959BD-C7AC-4D65-9980-A88510F776B8}']

function Add(a, b : Integer) : Integer; dispid 0;

function Subtract(a, b : Integer) : Integer; dispid 1;

function Equal(a, b : Integer) : WordBool; dispid 2;

end;

To create instance of the _Mathematics object and access the functions, see the code below:

Delphi

program MathematicsDemo;

{$APPTYPE CONSOLE}

{$R *.res}

uses

System.SysUtils,

CNClrLib.Host,

CNClrLib.Host.Helper,

CNClrLib.Core;

type

_Mathematics = dispinterface

['{D77959BD-C7AC-4D65-9980-A88510F776B8}']

function Add(a, b : Integer) : Integer; dispid 0;

function Subtract(a, b : Integer) : Integer; dispid 1;

function Equal(a, b : Integer) : WordBool; dispid 2;

end;

var

Console: _Console;

AMaths: _Mathematics;

begin

Console := CoConsole.CreateInstance;

try

//Load Assembly into the current Domain

.Net Runtime Library for Delphi

44

//Make sure the dll is in the same location as the EXE. If you

want to store

//the dll in a separate location, make sure you provide the full

path of the dll.

TClrAssembly.LoadFrom('Mathematics.dll');

//Create instance of the Mathematics Class

AMaths :=

_Mathematics(TClrDispatchActivator.CreateInstance('Mathematics.Mathema

tics'));

Console.WriteLine_15('Add(30, 50): {0}', AMaths.Add(30, 50));

Console.WriteLine_15('Subtract(30, 50): {0}', AMaths.Subtract(30,

50));

Console.WriteLine_15('Equal(30, 50): {0}', AMaths.Equal(30,

50));

Console.WriteLine_15('Equal(50, 50): {0}', AMaths.Equal(50,

50));

except

on E: Exception do

Console.WriteLine_15('Exception: {0}', E.Message);

end;

end.

//Output

//Add(30, 50): 80

//Subtract(30, 50): -20

//Equal(30, 50): False

//Equal(50, 50): True

3.2.7 How to: Receive First-Chance Exception

Notifications The FirstChanceException event of the AppDomain interface lets you receive a notification that an exception has been

thrown, before the common language runtime has begun searching for exception handlers. The event is raised at the

application domain level. A thread of execution can pass through multiple application domains, so an exception that is

unhandled in one application domain could be handled in another application domain. The notification occurs in each

application domain that has added a handler for the event, until an application domain handles the exception. The

procedures and examples in this article show how to receive first-chance exception notifications in a simple program

that has one application domain, and in an application domain that you create.

Receiving First-Chance Exception Notifications in the Default

Application Domain To demonstrate first-chance exception notifications in the default application

domain

Define an event handler for the FirstChanceException event. In this example, the event handler prints the name of the application domain where the event was handled and the exception's Message property.

Delphi

program FirstChanceException;

{$APPTYPE CONSOLE}

CNClrLib_Core_Intf__AppDomain.html

.Net Runtime Library for Delphi

45

{$R *.res}

uses

System.SysUtils,

CNClrLib.Host,

CNClrLib.Core;

var

Console: _Console;

FirstChangeEventPtr: TClrEventHandler;

procedure FirstChanceEventHandler(ASender: _ClrObject; Args:

_ClrEventArgs); stdcall;

var

EvtArgs: _FirstChanceExceptionEventArgs;

begin

EvtArgs := CoFirstChanceExceptionEventArgs.Wrap(Args.EventArgs);

Console.WriteLine_17('FirstChanceException event raised in {0}:

{1}',

TClrAppDomain.GetCurrentDomain.FriendlyName,

EvtArgs.Exception.Message);

end;

begin

Console := CoConsole.CreateInstance;

try

FirstChangeEventPtr := FirstChanceEventHandler;

TClrAppDomain.GetCurrentDomain.AddFirstChanceException(nil,

@FirstChangeEventPtr);

except

on E: Exception do

Console.WriteLine_15('Exception: {0}', E.Message);

end;

end.

.Net Runtime Library for Delphi

46

.Net Runtime Library for Delphi

47

Throw an exception and catch it. Before the runtime locates the exception handler, the

FirstChanceException event is raised and displays a message. This message is followed

by the message that is displayed by the exception handler.

Delphi

program ThrowArgumentException;

{$APPTYPE CONSOLE}

{$R *.res}

uses

System.SysUtils,

CNClrLib.Host,

CNClrLib.Host.Helper,

CNClrLib.Core;

var

Console: _Console;

ArgumentException: _ArgumentException;

begin

Console := CoConsole.CreateInstance;

try

ArgumentException := CoArgumentException.CreateInstance('Thrown in

' + TClrAppDomain.GetCurrentDomain.FriendlyName);

raise

EClrException.Create(ArgumentException.AsSystemException.AsException);

.Net Runtime Library for Delphi

48

except

on E: EClrException do

Console.WriteLine_17('ArgumentException caught in {0}: {1}',

TClrAppDomain.GetCurrentDomain.FriendlyName, E.Message);

end;

end.

.Net Runtime Library for Delphi

49

Throw an exception, but do not catch it. Before the runtime looks for an exception

handler, the FirstChanceException event is raised and displays a message. There is no

exception handler, so the application terminates.

Delphi

program FirstChanceException2;

{$APPTYPE CONSOLE}

{$R *.res}

uses

System.SysUtils,

CNClrLib.Host,

CNClrLib.Host.Helper,

CNClrLib.Core;

var

Console: _Console;

ArgumentException: _ArgumentException;

FirstChangeEventPtr: TClrEventHandler;

procedure FirstChanceEventHandler(ASender: _ClrObject; Args:

_ClrEventArgs); stdcall;

var

EvtArgs: _FirstChanceExceptionEventArgs;

begin

EvtArgs := CoFirstChanceExceptionEventArgs.Wrap(Args.EventArgs);

Console.WriteLine_17('FirstChanceException event raised in {0}:

{1}',

TClrAppDomain.GetCurrentDomain.FriendlyName,

EvtArgs.Exception.Message);

end;

begin

.Net Runtime Library for Delphi

50

Console := CoConsole.CreateInstance;

try

FirstChangeEventPtr := FirstChanceEventHandler;

TClrAppDomain.GetCurrentDomain.AddFirstChanceException(nil,

@FirstChangeEventPtr);

ArgumentException := CoArgumentException.CreateInstance('Thrown in

' + TClrAppDomain.GetCurrentDomain.FriendlyName);

EClrException.ThrowDotNetException(ArgumentException.AsSystemException

.AsException);

except

on E: EClrException do

Console.WriteLine_17('ArgumentException caught in {0}: {1}',

TClrAppDomain.GetCurrentDomain.FriendlyName, E.Message);

end;

end.

.Net Runtime Library for Delphi

51

Receiving First-Chance Exception Notifications in Another

Application Domain

If your program contains more than one application domain, you can choose which application domains receive

notifications.

To receive first-chance exception notifications in an application domain

that you create

Define an event handler for the FirstChanceException event. This example uses a static method that prints the name of the application domain where the event was handled and the exception's Message property.

Delphi

.Net Runtime Library for Delphi

52

procedure FirstChanceEventHandler(ASender: _ClrObject; Args:

_ClrEventArgs); stdcall;

var

EvtArgs: _FirstChanceExceptionEventArgs;

begin

EvtArgs := CoFirstChanceExceptionEventArgs.Wrap(Args.EventArgs);

Console.WriteLine_17('FirstChanceException event raised in {0}:

{1}',

TClrAppDomain.GetCurrentDomain.FriendlyName,

EvtArgs.Exception.Message);

end;

Create an application domain and add the event handler to the FirstChanceException event for that application

domain. In this example, the application domain is named AD1.

Delphi

...

var

FirstChangeEventPtr: TClrEventHandler;

AppD: TClrAppDomain;

begin

FirstChangeEventPtr := FirstChanceEventHandler;

AppD := TClrAppDomain.Create('AD1');

.Net Runtime Library for Delphi

53

AppD.AddFirstChanceException(nil, @FirstChangeEventPtr);

...

See Also

Raise and Consume Events

3.2.8 Resolving Assembly Loads The Framework Library provides the TClrAppDomain.AssemblyResolve event for applications that require greater

control over assembly loading. By handling this event, your application can load an assembly into the load context from

outside the normal probing paths, select which of several assembly versions to load, emit a dynamic assembly and

return it, and so on. This topic provides guidance for handling the AssemblyResolve event.

Note

For resolving assembly loads in the reflection-only context, use the

TClrAppDomain.ReflectionOnlyAssemblyResolve event instead.

How the AssemblyResolve Event Works

When you register a handler for the AssemblyResolve event, the handler is invoked whenever the runtime fails to bind

to an assembly by name. For example, calling the following methods from user code can cause the AssemblyResolve

event to be raised:

An TClrAppDomain.Load method overload or TClrAssembly.Load method overload whose first argument is a string that represents the display name of the assembly to load (that is, the string returned by the

TClrAssembly.FullName property).

An TClrAppDomain.Load method overload or TClrAssembly.Load method overload whose first argument is an AssemblyName object that identifies the assembly to load.

An TClrAssembly.LoadWithPartialName method overload.

An TClrAppDomain.CreateInstance method overload that instantiates an object in another application domain.

What the Event Handler Does

The handler for the AssemblyResolve event receives the display name of the assembly to be loaded, in the

ResolveEventArgs.Name property. If the handler does not recognize the assembly name, it returns null.

If the handler recognizes the assembly name, it can load and return an assembly that satisfies the request. The following

list describes some sample scenarios.

CNClrLib_Core_Intf__AssemblyName.htmlCNClrLib_Core_Intf__ResolveEventArgs.html

.Net Runtime Library for Delphi

54

If the handler knows the location of a version of the assembly, it can load the assembly by using the TClrAssembly.LoadFrom or TClrAssembly.LoadFile method, and can return the loaded assembly if successful.

If the handler has access to a database of assemblies stored as byte arrays, it can load a byte array by using one of the TClrAssembly.Load method overloads that take a byte array.

The handler can generate a dynamic assembly and return it. It is the responsibility of the event handler to return a suitable assembly. The handler can parse the display name of the

requested assembly by passing the ResolveEventArgs.Nameproperty value to the

CoAssemblyName.CreateInstance(WideString) . The event handler can return a different version of the assembly

than the version that was requested.

In most cases, the assembly that is returned by the handler appears in the load context, regardless of the context the

handler loads it into. For example, if the handler uses the TClrAssembly.LoadFrom method to load an assembly into the

load-from context, the assembly appears in the load context when the handler returns it. However, in the following case

the assembly appears without context when the handler returns it:

The handler loads an assembly without context.

The ResolveEventArgs.RequestingAssembly property is not null.

The requesting assembly (that is, the assembly that is returned by the ResolveEventArgs.RequestingAssembly property) was loaded without context.

Multiple versions of the same assembly can be loaded into the same application domain. This practice is not

recommended, because it can lead to type assignment problems.

What the Event Handler Should Not Do

The primary rule for handling the AssemblyResolve event is that you should not try to return an assembly you do not

recognize. When you write the handler, you should know which assemblies might cause the event to be raised. Your

handler should return null for other assemblies.

When loading an assembly, the event handler must not use any of the TClrAppDomain.Load or TClrAssembly.Load

method overloads that can cause the AssemblyResolve event to be raised recursively, because this can lead to a stack

overflow. This happens even if you provide exception handling for the load request, because no exception is thrown

until all event handlers have returned. Thus, the following code results in a stack overflow if MyAssembly is not found:

Delphi

program BadExample;

{$APPTYPE CONSOLE}

{$R *.res}

uses

System.SysUtils,

CNClrLib.Host,

CNClrLib.Core,

CNClrLib.Core.Intf;

var

Console: _Console;

AssemblyResolve: TClrEventHandlerR;

CNClrLib_Core_Intf__ResolveEventArgs.htmlCNClrLib_Core_Intf__ResolveEventArgs.htmlCNClrLib_Core_Intf__ResolveEventArgs.html

.Net Runtime Library for Delphi

55

procedure MyHandler(ASender: _ClrObject; AEventArgs: _ClrEventArgs;

out ReturnValue: _ClrObject); stdcall;

var

AResolveEventArgs: _ResolveEventArgs;

begin

AResolveEventArgs := CoResolveEventArgs.Wrap(AEventArgs.EventArgs);

Console.WriteLine_15('Resolving {0}', AResolveEventArgs.Name);

ReturnValue :=

TClrAssembly.Load(AResolveEventArgs.Name).AsClrObject;

end;

begin

Console := CoConsole.CreateInstance;

AssemblyResolve := MyHandler;

TClrAppDomain.GetCurrentDomain.AddAssemblyResolve(nil,

@AssemblyResolve);

try

TClrAppDomain.GetCurrentDomain.DefaultInterface.CreateInstanceAndUnwra

p('MyAssembly, version=1.2.3.4, culture=neutral, publicKeyToken=null',

'MyType');

except

on E: Exception do

Console.WriteLine_14(E.Message);

end;

Console.ReadKey;

end.

(* This example produces output similar to the following:

.Net Runtime Library for Delphi

56

Resolving MyAssembly, Version=1.2.3.4, Culture=neutral,

PublicKeyToken=null

Resolving MyAssembly, Version=1.2.3.4, Culture=neutral,

PublicKeyToken=null

...

Resolving MyAssembly, Version=1.2.3.4, Culture=neutral,

PublicKeyToken=null

Resolving MyAssembly, Version=1.2.3.4, Culture=neutral,

PublicKeyToken=null

Process is terminated due to StackOverflowException.

*)

3.3 Create Instance of .Net Objects In order to interact with .Net Objects's methods, properties, Fields and events, you need to

create an instance of the object. There are several ways to Create an Instance of a .Net Object in

Delphi using the Delphi Framework Library (DFL). These are:

Using Reflection Using Common Language Runtime Object (ClrObject) Using Constructor CoClasses

Using Reflection to Create instance of .Net Objects

There are several classes and methods that can be used to create instances of .Net Objects. The

mechanism used to create these instances is through reflection. For more information about

using Reflection in Delphi using DFL. For more information, see Reflection Overview.

The following methods can be used to create instances of .Net Objects through reflections:

TClrAppDomain.CreateInstance: This method creates a new instance of the specified

type defined in the specified assembly.

Delphi

program AppDomainCreateInstance;

{$APPTYPE CONSOLE}

{$R *.res}

uses

System.SysUtils,

CNClrLib.Host,

.Net Runtime Library for Delphi

57

CNClrLib.Core;

var

CurrentAppD: TClrAppDomain;

ObjHandle: _ObjectHandle;

ObjUnwrap: Variant;

begin

CurrentAppD := TClrAppDomain.GetCurrentDomain;

ObjHandle := CurrentAppD.CreateInstance('MyAssembly,

version=1.2.3.4, culture=neutral, publicKeyToken=null', 'MyType');

ObjUnwrap := ObjHandle.Unwrap_;

end.

TClrAppDomain.CreateInstanceFrom: This method createa a new instance of a specified

type defined in the specified assembly file.

Delphi

program AppDomainCreateInstanceFrom;

{$APPTYPE CONSOLE}

{$R *.res}

uses

System.SysUtils,

CNClrLib.Host,

.Net Runtime Library for Delphi

58

CNClrLib.Core;

var

CurrentAppD: TClrAppDomain;

ObjHandle: _ObjectHandle;

ObjUnwrap: Variant;

begin

CurrentAppD := TClrAppDomain.GetCurrentDomain;

ObjHandle :=

CurrentAppD.CreateInstanceFrom('C:\Temp\Mathematics.dll', 'MyType');

ObjUnwrap := ObjHandle.Unwrap_;

//Note the ObjectHandle.Unwrap is different from

ObjectHandle.Unwrap_.

//The Unwrap method returns the original .Net ObjectHandle object

whereas the

//Unwrap_ returns the .net wrapped object

end.

.Net Runtime Library for Delphi

59

TClrAppDomain.CreateComInstanceFrom: This method creates a new instance of a

specified COM type. Parameters specify the name of a file that contains an assembly

containing the type and the name of the type.

Delphi

program AppDomainCreateComInstanceFrom;

{$APPTYPE CONSOLE}

{$R *.res}

uses

System.SysUtils,

CNClrLib.Host,

CNClrLib.Core;

var

CurrentAppD: TClrAppDomain;

ObjHandle: _ObjectHandle;

ObjUnwrap: Variant;

begin

CurrentAppD := TClrAppDomain.GetCurrentDomain;

ObjHandle := CurrentAppD.CreateComInstanceFrom('MyCOM_Assembly,

version=1.2.3.4, culture=neutral, publicKeyToken=null', 'MyType');

ObjUnwrap := ObjHandle.Unwrap_;

//Note the ObjectHandle.Unwrap is different from

ObjectHandle.Unwrap_.

//The Unwrap method returns the original .Net ObjectHandle object

whereas the

//Unwrap_ returns the .net wrapped object

end

.Net Runtime Library for Delphi

60

All Create Instance Methods in TClrActivator class: The class contains methods to create

types of objects locally or remotely, or obtain references to existing remote objects.

Delphi

program ActivatorCreateInstance;

{$APPTYPE CONSOLE}

{$R *.res}

uses

System.SysUtils,

CNClrLib.Host,

CNClrLib.Core,

CNClrLib.EnumTypes;

var

Obj: Variant;

ObjHandle: _ObjectHandle;

ClrObject: _ClrObject;

begin

.Net Runtime Library for Delphi

61

//This method create Instance of ArrayList type by name using that

type's default constructor

Obj := TClrActivator.CreateInstance('System.Collections.ArrayList');

//This method creates an instance of the ArrayList type by name

using the constructor that best matches the specified parameters.

//In this case the parameter is an integer, hence the ArrayList

Constructor with Capacity as parameter will be invoked.

Obj := TClrActivator.CreateInstance('System.Collections.ArrayList',

[10]);

//Same as above except this method accepts _ObjectArray

Obj := TClrActivator.CreateInstance('System.Collections.ArrayList',

TClrArrayHelper.ToObjectArray([10]));

//This method create Instance of ArrayList type using that type's

default constructor

Obj :=

TClrActivator.CreateInstance(TClrAssembly.GetType('System.Collections.

ArrayList'));

//This method creates an instance of the ArrayList type using the

constructor that best matches the specified parameters.

//In this case the parameter is an integer, hence the ArrayList

Constructor with Capacity as parameter will be invoked.

//A Binding attribute is part of the method definition which

controls the binding and the

//way in which the search for members and types is conducted by

reflection.

Obj :=

TClrActivator.CreateInstance(TClrAssembly.GetType('System.Collections.

ArrayList'),

[10], [bfInstance, bfPublic], nil);

//This method creates an instance of the type whose name is

specified, using

//the named assembly file and the constructor that best matches the

specified parameters.

//A Binding attribute is part of the method definition which

controls the binding and the

.Net Runtime Library for Delphi

62

//way in which the search for members and types is conducted by

reflection.

ObjHandle :=

TClrActivator.CreateInstanceFrom('C:\Temp\Mathematics.dll', 'SumData',

True, [bfInstance, bfPublic], nil,

TClrArrayHelper.ToObjectArray([2, 5]));

Obj := ObjHandle.Unwrap_;

//This method creates an instance of the COM object whose name is

specified.

ObjHandle := TClrActivator.CreateComInstance('MyCOM_Assembly,

version=1.2.3.4, culture=neutral, publicKeyToken=null', 'MyType');

Obj := ObjHandle.Unwrap_;

//Create an Instance of ArrayList type by name with no parameter and

return ClrObject

ClrObject :=

TClrActivator.ClrCreateInstance('System.Collections.ArrayList');

Obj := ClrObject.Unwrap;

end.

.Net Runtime Library for Delphi

63

All the Methods in TClrDispatchActivator Class : The class contains methods to create

types of objects and return type will be Dispatch Interface instaed of Unknown Variant

(IUnknown). These create instance methods in this class are required if you want ot

create a library in .net with DispIDs and access them directly in delphi using

dispinterfaces. For more information see Access External .Net Types using COM

Dispatch.

Access_External_.Net_Types_using_COM_Dispatch.htmAccess_External_.Net_Types_using_COM_Dispatch.htm

.Net Runtime Library for Delphi

64

Delphi

program DispatchActivatorCreateInstance;

{$APPTYPE CONSOLE}

{$R *.res}

uses

System.SysUtils,

CNClrLib.Host,

CNClrLib.Core;

var

Obj: IDispatch;

begin

//This method create Instance of ArrayList type by name using that

type's default constructor

Obj :=

TClrDispatchActivator.CreateInstance('System.Collections.ArrayList');

//This method creates an instance of the ArrayList type by name

using the constructor that best matches the specified parameters.

//In this case the parameter is an integer, hence the ArrayList

Constructor with Capacity as parameter will be invoked.

Obj :=

TClrDispatchActivator.CreateInstance('System.Collections.ArrayList',

[10]);

//Same as above except this method accepts _ObjectArray

Obj :=

TClrDispatchActivator.CreateInstance('System.Collections.ArrayList',

TClrArrayHelper.ToObjectArray([10]));

end.

.Net Runtime Library for Delphi