Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

C# ПІДРУЧНИКИ / c# / MS Press - Msdn Training Programming Net Framework With C#

.pdf
Скачиваний:
194
Добавлен:
12.02.2016
Размер:
16.87 Mб
Скачать

Module 15 (Optional): Interoperating Between Managed and Unmanaged Code

35

 

 

 

Although the import process generally produces accurate interop assemblies, there are cases when you can (or must) modify the interop assembly to produce a custom RCW.

There are several reasons why you might customize an RCW, such as:

!One or more types require additional marshaling information.

!A type library contains many specialized types that are unrecognizable to the marshaler.

!A large type library can include types that are unnecessary for an application.

You can eliminate the need to deploy unnecessary types by creating an interop assembly from managed source code.

If you must customize the runtime callable wrapper with additional or different marshaling instructions, you can either:

1.Edit the interop assembly, searching for problematic syntax and replacing it with alternative syntax.

This option is best for minor marshaling changes.

2.Create a wrapper manually, based on an existing Interface Definition Language (IDL) file or type library.

Declaring COM types manually is a difficult activity that requires working knowledge of the Type Library Importer (Tlbimp.exe), the default behavior of the interop marshaler, and COM. This approach is best used when you have an entire library of specialized types or require the RCW source code.

For more information about implementing these choices, see the .NET

Framework Software Development Kit (SDK) documentation.

36

Module 15 (Optional): Interoperating Between Managed and Unmanaged Code

Performance and Security Issues

Topic Objective

To list some performance issues that arise from running unmanaged code from managed code.

Lead-in

Running unmanaged code from managed code decreases the performance of your application.

!Recognize that transitions that occur when managed code must interact with unmanaged code result in an overhead of 10 to 40 instructions per call.

#Limit the number of transitions that appear in your code

#Instead, use API calls that perform several actions at once

!Eliminate the creation of the proxy and stub by setting the ApartmentState on the thread before creating a COM object

!For trusted code, suppress security checks that are performed when managed code calls unmanaged code

*****************************ILLEGAL FOR NON-TRAINER USE******************************

Transitions occur when managed code must interact with unmanaged code. A slight overhead is associated with every transition. These overheads require 10 to 40 instructions per call. The best practice is to limit the number of transitions that appear in your code. If you must use transitions, use API calls that perform several actions from the same call instead of ones that only perform few actions and must be repeatedly called.

Threading models that are used in managed and unmanaged code affect the performance of applications. Whenever a COM object and a managed thread are in incompatible apartments, all calls on the object are made through a COM-created proxy. To eliminate the use of proxies and stubs, and significantly enhance performance, set the ApartmentState on the thread before creating the object.

Security checks that are performed when unmanaged code is run, also lead to a decrease in application performance. You can suppress these security checks and increase the performance of your application.

When managed code calls unmanaged COM code by using COM interoperability services, a demand for the UnmanagedCode permission is made to ensure that all callers have the necessary permission to allow the call to proceed. You can suppress the demand for the UnmanagedCode permission at run time by using the SuppressUnmanagedCodeSecurityAttribute attribute. The demand for the UnmanagedCode permission will still occur at link time.

Module 15 (Optional): Interoperating Between Managed and Unmanaged Code

37

 

 

 

The SuppressUnmanagedCodeSecurityAttribute attribute helps improve code performance by suppressing asserts and demands at run time. These run time asserts and demands are the usual security checks performed when calling unmanaged code. Only code that has been granted the UnmanagedCode permission can use the SuppressUnmanagedCodeSecurityAttribute attribute, however. Using this attribute in a class or module applies to all methods contained in the class or module.

When you use the SuppressUnmanagedCodeSecurityAttribute attribute in a class, code that does not have permission to access unmanaged code can call methods in the class to access unmanaged code. Therefore, you must make sure that when you use the SuppressUnmanagedCodeSecurityAttribute attribute, you write secure code. Otherwise, your code can be misused by malicious code.

38

Module 15 (Optional): Interoperating Between Managed and Unmanaged Code

Best Practices

Topic Objective

To list some best practices to be followed when calling COM components from managed code.

Lead-in

Let’s look at some best practices that you should use when calling COM components from managed code.

!The MSIL Disassembler can be used on the generated assembly to determine the exact names of the namespace and classes that are generated

!Any parameter passed by reference in C++ or

Visual Basic 6.0 will generate a parameter that needs to be passed by using the ref keyword in C#

*****************************ILLEGAL FOR NON-TRAINER USE******************************

If you create your runtime callable wrapper assembly by adding a reference to a COM object in Visual Studio .NET or by using the Type Library Importer, the namespace and class names that are generated might not always be obvious. To view these names, you can run the MSIL Disassembler on the particular assembly. If you create the runtime callable wrapper assembly with

Visual Studio .NET, you must attempt to build the project once to generate the assembly.

Parameters passed by reference in unmanaged code frequently require the use of the ref keyword when that code is called by using C#. For C or C++, this includes most parameters passed as pointers. For Visual Basic 6.0, keep in mind that, by default, all parameters are passed by reference. The most notable exception to this is for passing string types, which can usually be passed as String or StringBuilder objects from managed code. For an example in C or C++ of passing a string type, see Marshaling in this module.

Module 15 (Optional): Interoperating Between Managed and Unmanaged Code

39

 

 

 

Lab 15.2: Calling COM Objects

Topic Objective

To introduce the lab.

Lead-in

In this lab, you will call a COM object from managed code.

*****************************ILLEGAL FOR NON-TRAINER USE******************************

Objectives

After completing this lab, you will be able to call a COM object from managed code.

Estimated time to complete this lab: 30 minutes

40

Module 15 (Optional): Interoperating Between Managed and Unmanaged Code

Exercise 1

Calling a COM Object From Managed Code

In this exercise, you will call a COM object from managed code. This includes registering the COM DLL, adding a reference to the COM object in a

Visual Studio .NET project, and then adding code to call the COM object.

Important To use Microsoft Visual Studio .NET tools within a command prompt window, the command prompt window must have the proper environment settings. The Visual Studio .NET Command Prompt window provides such an environment. To run a Visual Studio .NET Command Prompt window, click Start, All Programs, Microsoft Visual Studio .NET,

Visual Studio .NET Tools, and Visual Studio .NET Command Prompt.

!Register the COM object

1.At the command prompt, change the current folder to <install folder>\Labs\ Lab15\Lab15.2\Starter.

2.To register the COM object, run regsvr32 VBUnmanagedCalculator.dll.

3.A dialog box appears informing you that the registration succeeded. Click OK to dismiss the dialog box.

!Open the Visual Studio .NET project for this exercise and examine the application UI

1.In Windows Explorer, move to <install folder>\Labs\Lab15\Lab15.2\ Starter.

2.Double-click CallingComFromDotNet.csproj to open the project for this exercise in Visual Studio .NET.

3.In the Solution Explorer pane, double click CalcUI.cs. The UI design for the Windows Forms application appears. Examine the UI for a moment to become familiar with it.

4.Press F7 to edit the code that implements the Windows Form application.

Module 15 (Optional): Interoperating Between Managed and Unmanaged Code

41

 

 

 

! Add the reference to the COM object and attempt to build the project

1.On the Project menu, click Add Reference.

2.In the Add Reference dialog box, click the COM tab. In the list of registered COM objects, click VBUnmanagedCalculator.

3.To add VBUnmanagedCalculator to the Selected Components window, click Select.

4.To add the reference, click OK. Notice that the VBUnmanagedCalculator DLL is added to the project references.

5.On the Build menu, click Build Solution. Your application does not build successfully yet, but the runtime callable wrapper assembly for the

VBUnmanagedCalculator.dll is generated.

6.In a Visual Studio .NET Command Prompt window, change the current folder to <install folder>\Labs\Lab15\Lab15.2\ Starter\bin\Debug.

7.To view the metadata in the runtime callable wrapper assembly, at the command prompt, type ildasm /adv Interop.VBUnmanagedCalculator.dll

Use the MSIL Disassembler to view the namespace and classes created for the COM object.

! Modify the code in the project to call the COM object

1.In the CalcUI.cs file, find the first ‘TODO’ comment that instructs you to add a using statement for VBUnmanagedCalculator. Add the correct using statement. Notice that you can use the Task List tab in the lower-left hand pane to find the ‘TODO’ comments. Click View, select Show Tasks, and then click All if the ‘TODO’ comments do not appear in the task list.

2.Find the next ‘TODO’ comment that instructs you to instantiate a CalcEngine object. Add the code to instantiate a CalcEngine object and assign it to the calcEngine private member variable.

3.Scroll down to the next ‘TODO’ comment that instructs you to call GetVersion in CalcEngine. Add the code to make the call described and assign the results of the call to the VersionInfo text box.

4.Scroll down to the KeyDate_Click method. Complete the code in this method by replacing the ‘TODO’ comment with code to obtain the date by calling the GetDate method in CalcEngine and assign the results of the call to the OutputDisplay text box. Then, add code to reset the engine for the next equation by calling the CalcReset method in CalcEngine.

5.In the KeyClear_Click method, complete the code by replacing the ‘TODO’ comment with code that calls the CalcReset method in

CalcEngine and clears the OutputDisplay text box.

42Module 15 (Optional): Interoperating Between Managed and Unmanaged Code

!Build and test your application

1.On the File menu, click Save All.

2.On the Build menu, click Build Solution. Your application should build successfully. The following statement should appear as the last line of the output window:

Build: 1 succeeded, 0 failed, 0 skipped.

3.On the Debug menu, click Start. When the calculator appears, check the version number. It should read “Calculator – VB6 Unmanaged Component”. Enter some equations to test the application.

4.Close the application.

Note If you wish to test the solution project, you will first need to follow the steps in the “Register the COM object”, “Open the Visual Studio .NET project for this exercise and examine the application UI”, and “Add the reference to the COM object and attempt to build the project” procedures above.

Module 15 (Optional): Interoperating Between Managed and Unmanaged Code

43

 

 

 

" Calling .NET Objects from COM Objects

Topic Objective

To introduce how COM callable wrappers are used to expose .NET Framework classes to COM clients.

Lead-in

In this section, you will learn how to create COM callable wrappers to use .NET Framework types for a COM client.

!COM Callable Wrappers

!The Export Process

!Registering a .NET Framework Class with the System Registry

!Using the ClassInterfaceAttribute

!Using .NET Framework Types from COM

!Managed and Unmanaged Events

!Best Practices

*****************************ILLEGAL FOR NON-TRAINER USE******************************

The .NET Framework allows existing COM applications to use managed code transparently by generating COM callable wrappers for .NET Framework classes. These wrappers are generated at run time. COM callable wrappers are proxy objects that are generated from the metadata that is stored in an assembly, so COM applications can use the .NET Framework classes in the same manner as they would use COM components.

44

Module 15 (Optional): Interoperating Between Managed and Unmanaged Code

COM Callable Wrappers

Topic Objective

To describe how the runtime uses COM callable wrappers to expose managed classes to COM clients.

Lead-in

To allow COM clients to use a managed class, the .NET Framework creates a COM callable wrapper.

*****************************ILLEGAL FOR NON-TRAINER USE******************************

COM clients cannot reference a .NET Framework object directly. When a COM client calls a .NET Framework object, the common language runtime creates the managed object and a proxy for the managed object called the COM callable wrapper.

The purpose of a COM callable wrapper is to marshal calls between managed and unmanaged code, and to manage the identity and lifetime of the managed object it wraps. COM callable wrappers are invisible to other classes running within the .NET Framework. Unlike the managed object it wraps, the COM callable wrapper is allocated memory from a non-collected heap. This makes it possible for COM clients to reference the wrapper directly.

COM callable wrappers are reference-counted in the traditional COM fashion. When the reference count on the wrapper reaches zero, the wrapper releases its reference on the managed object. A managed object with no remaining references is collected during the next garbage-collection cycle.

The runtime creates one COM callable wrapper for a managed object, regardless of the number of COM clients requesting its services. The COM callable wrapper, in turn, holds a single reference to the managed object that implements the interface. Both COM clients and .NET Framework clients can make requests on the same managed object simultaneously.

When you compile your managed code into an assembly, metadata describing each type in the assembly is generated. The Type Library Exporter can be used to create a type library file from the metadata for your assembly. COM clients can then import the type library and use the managed object like any other COM object. When the COM client tries to create and access a managed object from the assembly, the runtime uses the assembly’s metadata to generate a COM callable wrapper. The wrapper marshals the call between the COM client and the managed object.

Соседние файлы в папке c#