Tải bản đầy đủ - 0 (trang)
12-10. Expose a .NET Component Through COM

12-10. Expose a .NET Component Through COM

Tải bản đầy đủ - 0trang


In addition, you should consider the following recommendations:

You should not create inheritance relationships between classes, because these

relationships will not be visible to COM clients (although .NET will attempt to

simulate this by declaring a shared base class interface).

The classes you are exposing should implement an interface. For added versioning

control, you can use the attribute System.Runtime.InteropServices.GuidAttribute

to specify the GUID that should be assigned to an interface.

Ideally, you should give the managed assembly a strong name so that it can be

installed into the GAC and shared among multiple clients.

In order for a COM client to create the .NET object, it requires a type library (a TLB file). The type

library can be generated from an assembly using the Tlbexp.exe command-line utility. Here is an

example of the syntax you use:

tlbexp ManagedLibrary.dll

Once you generate the type library, you can reference it from the unmanaged development tool.

With Visual Basic 6, you reference the TLB file from the Project References dialog box. In Visual C++, you

can use the #import statement to import the type definitions from the type library.




C H A P T E R 13


Commonly Used Interfaces

and Patterns

The recipes in this chapter show you how to implement patterns you will use frequently during the

development of Microsoft .NET Framework applications. Some of these patterns are formalized using

interfaces defined in the .NET Framework class library. Others are less rigid, but still require you to take

specific approaches to their design and implementation of your types. The recipes in this chapter

describe how to do the following:

Create custom serializable types that you can easily store to disk, send across the

network, or pass by value across application domain boundaries (recipe 13-1)

Provide a mechanism that creates accurate and complete copies (clones) of

objects (recipe 13-2)

Implement types that are easy to compare and sort (recipe 13-3)

Support the enumeration of the elements contained in custom collections using a

default or custom iterator (recipes 13-4 and 13-5)

Ensure that a type that uses unmanaged resources correctly releases those

resources when they are no longer needed (recipe 13-6)

Display string representations of objects that vary based on format specifiers

(recipe 13-7)

Correctly implement custom exception and event argument types, which you will

use frequently in the development of your applications (recipes 13-8 and 13-9)

Implement the commonly used Singleton and Observer design patterns using the

built-in features of C# and the .NET Framework class library (recipes 13-10 and


Implement the producer/consumer pattern to coordinate multiple threads or

tasks safely (recipe 13-12)

Defer initialization of a type until the first time it is used (recipe 13-13)

Define a method that has optional parameters with default values (recipe 13-14).




Define an extension method (recipe 13-15)

Invoke type members dynamically and without static checking (recipe 13-16)

Create variant generic types (recipe 13-18)

13-1. Implement a Custom Serializable Type


You need to implement a custom type that is serializable, allowing you to do the following:

Store instances of the type to persistent storage (for example, a file or a database)

Transmit instances of the type across a network

Pass instances of the type by value across application domain boundaries


For serialization of simple types, apply the attribute System.SerializableAttribute to the type

declaration. For types that are more complex, or to control the content and structure of the serialized

data, implement the interface System.Runtime.Serialization.ISerializable.

How It Works

Recipe 2-13 showed how to serialize and deserialize an object using the formatter classes provided with

the .NET Framework class library. However, types are not serializable by default. To implement a custom

type that is serializable, you must apply the attribute SerializableAttribute to your type declaration. As

long as all of the data fields in your type are serializable types, applying SerializableAttribute is all you

need to do to make your custom type serializable. If you are implementing a custom class that derives

from a base class, the base class must also be serializable.

■ Caution Classes that derive from a serializable type don’t inherit the attribute SerializableAttribute. To

make derived types serializable, you must explicitly declare them as serializable by applying the

SerializableAttribute attribute.

Each formatter class contains the logic necessary to serialize types decorated with

SerializableAttribute, and will correctly serialize all public, protected, and private fields. You can

exclude specific fields from serialization by applying the attribute System.NonSerializedAttribute to

those fields. As a rule, you should exclude the following fields from serialization:




Fields that contain unserializable data types

Fields that contain values that might be invalid when the object is deserialized,

such as database connections, memory addresses, thread IDs, and unmanaged

resource handles

Fields that contain sensitive or secret information, such as passwords, encryption

keys, and the personal details of people and organizations

Fields that contain data that is easily re-creatable or retrievable from other

sources, especially if there is a lot of data

■ Note See Recipe 2-14 for an example of using a slightly different method to exclude members from serialization

when using the JSON format.

If you exclude fields from serialization, you must implement your type to compensate for the fact

that some data will not be present when an object is deserialized. Unfortunately, you cannot create or

retrieve the missing data fields in an instance constructor, because formatters do not call constructors

during the process of deserializing objects. The best approach for achieving fine-grained control of the

serialization of your custom types is to use the attributes from the System.Runtime.Serialization

namespace described in Table 13-1. These attributes allow you to identify methods of the serializable

type that the serialization process should execute before and after serialization and deserialization. Any

method annotated with one of these attributes must take a single System.Runtime.Serialization.

StreamingContext argument, which contains details about the source or intended destination of the

serialized object so that you can determine what to serialize. For example, you might be happy to

serialize secret data if it’s destined for another application domain in the same process, but not if the

data will be written to a file.

Table 13-1. Attributes to Customize the Serialization and Deserialization Processs




Apply this attribute to a method to have it executed before the object is

serialized. This is useful if you need to modify object state before it is

serialized. For example, you may need to convert a DateTime field to UTC

time for storage.


Apply this attribute to a method to have it executed after the object is

serialized. This is useful in case you need to revert the object state to what

it was before the method annotated with OnSerializingAttribute was run.


Apply this attribute to a method to have it executed before the object is

deserialized. This is useful if you need to modify the object state prior to




Tài liệu bạn tìm kiếm đã sẵn sàng tải về

12-10. Expose a .NET Component Through COM

Tải bản đầy đủ ngay(0 tr)