Effective Visual Basic (Visual Basic Efficient Programming) (2)

xiaoxiao2021-03-06  43

??. Build and use COM-based components

# COM background Knowledge http://www.develop.com/tutorials/vbcom

2.1 Rules 2-1: Thinking from the perspective of the interface

# As long as a class is unchanged (or only new attributes / methods), the class customers do not have to change

2.2 Rules 2-2: Use custom interfaces

# Class You can implement new features by constantly introducing new custom interfaces while maintaining compatibility of the original client program.

# # 类 模 公 公 公 公 方法 方法 接 接

# Vb Generally custom interface via the publicnotcreatable class module

# IPLEMENTS IEmployee Interface Class CCONSULTANT, its default interface, even if it is empty, it can be used as a basis for the TypeOf judgment. IF TypeOf Remp I CCONSULTANT

# Customizing the interface After the release must be held (# 2.5), VB allows the default interface to expand by adding method (# 2.5.3)

# Scripting Environment Unable to use custom interfaces, you need to take other steps (# 4.5)

2.3 Rules 2-3: It is best to use IDL to independently define custom interfaces

#The interface to Typelib via the IDL file, you can avoid the redundant class module to define the interface definition interface class library using the publicnotcreatable class module, and the interface may be extended and the compatibility is disadvantageous.

# Use oleView.exe to confine the TypeLib in the ActiveX DLL to generate an IDL file, and then compile it to Typelib.

The content that needs to be modified includes: Single-> FLOATSTRUCT TAGX {...} -> struct x {...} Delete CoClass and other content to remove the interface name Prefix Underline ODL-> Object, Idispatch-> iUnknown Add Helpstring

Example: // Typelib Fileneme: Interfaces.dll [UUID (...), Version (1.0), Helpstring ("")] library interfaces {// Tlib // Tlib: Microsoft Ado: {} importlib ("msado15.dll") ; // Tlib: Ole Automation: {} importlib ("stdole2.tlb");}

[Object / * ODL * /, UUID (...), OleAutomation] Interface Iemployee: iUnknown / * idispatch * / {[id (1), propGet] HRESULT NAME ([OUT, RETVAL] BSTR * NAME); [ID (2 ), proput name ([in] bstr * name); [ID (3)] HRESULT READFROMDB ([IN, OUT] _Recordset **); [ID (4)] HRESULT ISSUEPAYCHECK ([OUT, RETVAL] CURRENCY * };

2.4 Rules 2-4: Use custom callback to avoid the limitations of class-based events

# VB6 The class-based event handling mechanism has some restrictions: WitHHevents can only be used for module-level reference variable arrays, collections, and local variables cannot be used in the event handling mechanism must be defined in the class module, so they cannot define multiple class sharing. Events, which means that events cannot be included in the custom interface.

# Custom Tune ## '** IREGISTERCLITOPTION EXPLICIT

Public Enum IREGISTERCLIENTERRORSEINTFNOTIMPLEMENTED = VBOBJECTERROR 8193EALREADYREGISTEREDENOTREGISTEREDEND ENUM

Public Sub Register (RClient as object) End Sublic Sub Unregister (RCLIENT AS Object) End Sub requires an object to trigger an event to implement the above interface so that customers can register themselves and require reception.

## '** IEMPLOYEEEVENTS I want to receive objects of the IEMPLOYEE object event Implement this interface public sub channel (REMP AS IEMPLOYEE) END SUB I hope that the client that receives the event should implement various events that may be caused by the object, respectively, respectively. Callback.

## The object example of the event '** cconsultantOption Explicit

Implements IEMPLOYEEIMPLEMPLEments IREGISTERCLIENT

Private Sname As StringPrivate RMYCLIENT AS IEMPLOYEEEVENTS '** If you need to handle multiple customers, here you have changed here, the register and unregister methods are modified

Private Sub IRegisterClient_Register (rClient As Object) If Not TypeOf rClient Is IEmployeeEvents ThenErr.Raise eIntfNotImplemented, ... ElseIf Not rMyClient Is Nothing ThenErr.Raise eAlreadyRegistered, ... ElseSet rMyClient = rClientEnd IfEnd Sub

Private sub Iregister (rclient as object) if NOT RMYCLIENT IS RCLIENT Thenerr.raise EnotRegisteldelseset RMYCLIENT = Nothing IFEND SUB

Private property Get IemPloyee_name () as stringiemployee_name = snameend Property

Private Property Let Iemployee_name (byval srs as string) Sname = SRHS

On Error ResMe next '** ignore unreachable / problematic client clientsrmyclient.changed me' ** name Was Changed, So Raise EvenTend Property

...

## 客户 端 示 '** FormTestOption Explicit

Private Colemployees As New Collection

Implements Iemployeeeeeeeeeeeeeee

Private Sub IemPloyeeevents_Changed (REMP As IEmployee) '** Update Form To Reflect Changes in Remp.NameEnd Sub

PRIVATE SUB FORM_LOAD () '** Open DB AND RETRIEVE AN RS of Employee Records

Dim Remp as IEMPLOYEEEEEEEEEEEEE, Robj As IREGisterClient

Do While Not rsEmployees.EOFSet rEmp = CreateObject (rsEmployees.Fields.Item ( "ProgID"). Value) If TypeOf rEmp Is IRegisterClient Then '** event basedSet rObj = rEmp' ** switch to register interfacerObj.Register Me '** And register myselft to receive refuseness ifRemp.readfromDB RSemployeescoleMPloyees.add remote a

'** Close DB and RSEND SUB

Private Sub Form_Unload (Cancel As Integer) Dim Remp as Iemployee, Robj As IREGIsterClientdim L As Long

For L = Colemployees.count to 1 Step -1set Remp = ColeMployees.Item (L) Colemployees.remove L

IF TypeOf Remp is IregisterClient Then '** Event BasedSet Robj = Remp' ** Switch To Register InterfaceRemp.unregister me '** and unregister myselfend ifnextend Sub

If you do not log out, the reference to the customer who is saved in the event object will cause the customer to not release.

# Note: When you trigger an event across the process / machine, you should pay attention to the subject to be licensed before you can call customers.

# You can implement a priority-based event notification scheme when you have multiple customers.

# Supplement: Multiple event customers can realize the relationship between Model-View mode

2.5 Rules 2-5: Keep compatibility with caution

# Realize the compatibility with the client needs attention: 1. The overall function of the server must maintain compatibility between the versions 2. Each class public interface cannot be changed: the method can not be deleted, the method name cannot be changed, the method The parameter table cannot be changed. 3. CLSID, IID, libid can't change

2.5.1 Script Client Program

# Script Client The default interface of the COM object is later binding (based on the iDispatch interface, first look for the method ID again, and use the Variant transfer parameter) and cannot access the custom interface. To remain compatible with script customers, you only need to keep the ProgID and the default interface content constant.

# VB object Progid determines the project name and class module name.

# Due to the use of Variant delivery parameters, the method parameter table in the interface even changes, as long as it is compatible (such as Integer to LONG), it does not affect the use of the client.

# In the compilation environment, if you use the Object or Variant variable to save object reference, you also use later bindings. Just use New to create an object, you need to keep the CLSID and the default interface IID unchanged.

2.5.2 Compiled client program

# Use the VTABLE binding when using a specific custom / default interface type variable to use the specific custom / default interface type variable. The interface must be defined in TypeLib and references in the programming environment.

# VB Compatibility Options: ## no compatibility Each time you compile, all GUID will be changed ## project compatibility clsid, libid will remain, but the IID will change. Before the design is completed. When compiled, Typelib version plus 1 ## binary compatibility All GUID will no longer change. Once the release is released, it should be switched to this setting. Note Retained released versions. After setting Binary Compatibility, if you change the interface (even if you change the type of only one parameter) and try to compile, VB will give an interrupt compatibility. 2.5.3 Version-compatible interface

# VB Support Under the Binary Compatibility setting, add a method to the default interface without warning, at this time, VB will add the method entry after the original vTable, generate a new IID identifier new interface, and put the original interface Call Forward to the new interface and add 0.1 to the TLB version. If the client installer does not register the necessary forwarding information in the system, it will result in a COM activation error in the runtime. (See MS KB241637)

# 安 安全 的 方法 是 使用用 use custom interfaces, and define new interfaces if different publishing versions need to change the interface. (# 2.3). See MS KB190078, 190967, 191214

2.6 Rules 2-6: Select the correct COM activation technology

# Several ways to create objects: MTS environment Set rEmp = New Employees.CConsultantSet rEmp2 = CreateObject ( "Employee.CConsultant") Set rEmp3 = GetObject ( "", "Employee.CConsultant") in: Set rEmp4 = GetObjectContext.CreateInstance ( "Employee.cconsultant") ASP environment: set remp5 = server.createObject ("Employees.cconsultant")

# When the specific type of reference variable declares, no matter how the object is created, it is bound to vTable. When the reference variable is an Object or a Variant type, it is binding in the later binding of how to create an object. The COM object written in VB supports two bindings.

2.6.1 COM activation

# COM INVOCATION (?) Is the process of creating a COM object at runtime, involving client programs, GUID, COM underlying services, one or more registry and COM servers. The purpose is to (1) Creating an object; (2) obtains the necessary interface references.

2.6.2 New operator

# New operator does not always trigger COM activation (CoCreateInstanceex executes COM activation), if the target class module is in the same VB project / dll / exe in the target class module, or in the same engineering group open in VB IDE, create an object The process is similar to NEW in C , which is much smaller than CoCreateInstanceex.

# Note Cerely Use the object reference variable declaration declaration (including the same form variable as the form type name), which may cause unnecessary objects (when a reference variable of such declaration is used in if robj is nothing When it is indeed Nothing, you will first trigger a New operation).

2.6.3 CREATEOBJECT

# CreateObject Always activate the object with COM.

# Can't use an instance of the VB class for the private, only for the registered publicnotable, and require the object to be created to implement the IDSPATCH interface regardless of whether the later binding is used. The components written by ATL may not implement this interface. 2.6.4 getObject

#Set rdoc getObject ("File.doc", "Word.Document") RDoc.Activate Specifies the empty file name to create a new object, similar to CreateObject, but cannot specify the remote server.

# 通过 服务步 调步 = = q..) 服务....) 服务))))).)))))))))

2.6.5 getObjectContext.createInstance and Server.createObject

# GetObjectContext.createInstance and Server.createObject are inherently packaging for the CreateObject function, but the MTS or ASP environment where the class is involved.

# Note: Use CreateObject and CreateInstance in COM to be safe. In ASP, you can use CreateInstance when you cannot use Server.createObject. See ms kb193230

2.6.6 Performance

# 影响 影响 的 om,, the Marshalling feature of the bind type and parameters is more discussion, but COM activation is also one of the factors that should be considered.

# No COM is active, New is the most efficient.

# COM activation is divided into processes, local, remote. The new most efficient time is activated in the ## process. When the activation process outside the ##, New create objects and obtain the default interface, IUnknown, IPersistStreamInit, IPersistPropertyBag 4 interfaces reference CreateObject and GetObject get IDispatch, IUnknown, IPersistStreamInit, IPersistPropertyBag 4 interfaces reference (requires two API calls and three method calls ) ## process activation needs to generate proxy / stub pairs, have some overhead. ## If the object does not perform a custom group, PROXY / STUB in connection with the default interface is much larger than the proxy / stub that creates COM predefined interfaces such as iDispatch. ## So, if you use a later binding or custom interface without the default interface, you will waste the proxy / stub of the new operation to contact the default interface during the New operation. ## Note Must use the post-binding method to reflect this advantage of CreateObject, otherwise if the early binding reference variable DIM ROBJ AS TLIBNAME.CCLASS is declared, the PROXY / PROXY / TRE / Stub pair. ## However, when calling the object's method, the overhead of the later binding mode is large. If you need multiple calling methods (rough local> = 10, remote> = 3), the advantage of CreateObject / getObject when you create an object is offset. ## If the system runs on Windows 2000, create an object using GetObject ("New: TlibName.cclass") only needs to get a reference to the IDispatch and iUnknown interface. If you don't need to use the IPersistStreaminit and IPersistPropertyBag interface, you can improve efficiency. ## Another inconvenience in the later binding: IntelliSense and type check capabilities cannot be used. 2.7 Rules 2-7: Carefully use Class_Terminate

# Prepare the Close / Dispose method when you takeshore some non-memory resources (such as files, shared memory, network connection, Ado connection, recordset, etc.).

# If the design allows the object to be re-open or used, provide a Close method, otherwise provide a Dispose method.

2.8 Rules 2-8: Modeling based on sessions instead of entities

#Natabases, which are more interactive, based on session processes, can improve the efficiency of interaction. (# 5.2)

## The example of entity model with rcusTomer.StreetAddr = <...>. City = <...>. State = <...>. Zip = <...> end with each property requires a network Overhead

## r 基 建于 建 例 r> 建 基 这... 建. 建. 建. 建. 建. 建.. Thinking: The purpose of design modeling is to achieve design objectives such as improvement under various restrictions, rather than just pursue design.

2.9 Rules 2-9: In addition to simple small-scale application systems, avoid using ACTIVEX executables

# Process Outside Objects include an advantage of ActiveX EXE or ActiveX DLL # process outside MTS / COM (MTS 3.0): 1) fault isolation. The collapse of the object does not cause the customer's crash, and vice versa. 2) Separate security identity mechanisms, objects can be run different from the client's user. 3) Multithreaded service, customers can activate multiple objects or execute function calls in parallel. 4) You can run the object on a machine different from the client program. The last one makes the distributed multi-layer application system possible.

# ActiveX EXE is only designed to meet the needs of small-scale systems. MTS or COM also provides secure, resource sharing, distributed transaction, and configuration / process management.

# ActiveX EXE Optional Thread Model: Thread pool = 1 Single-Threader - Requests Need to Queu THREAD POOL> 1 Limit the number of concurrent threads - the number of Ththread Per Object uses different threads for different customer service - the maximum ability, But the load is larger than the performance.

# ActiveX EXE security depends on DCOMCFG.EXE configuration

# Note: The global variable defined in the BAS module is only globally in the same Apartment and cannot be shared between processes. MTS or COM provides Shared Properties.

转载请注明原文地址:https://www.9cbs.com/read-62862.html

New Post(0)