net runtime library for delphi - sourceforge.net · 4.3.2 generating source code and compiling a...
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