|
|
|
There is quite a lot of misunderstanding among COM newbies about what really happens when a COM interface is passed as a method parameter. As in most of the cases, VB programmers are protected from a lot of details on the COM run-time, but you do have to know such details if you want to assemble something that perform decently in a distributed environment.
1) Basic automation types (Double, Long, String) are passed by value if the method signature is declared ByVal. They are passed by reference if the method signature is declared ByRef. The behavior you experience is the same if the method call takes place in-Apartment or cross-Apartment. 2) COM Interfaces: The first thing to emphasize here is that in VB (or in any COM-aware language) you never get in touch with a Class (the client doesn't have to know the class binary layout!); instead, you get in touch with interfaces. So when you think you're passing an object you are actually passing an interface. The state of underlying COM object that is behind the interface is not copied, e.g. as a struct (a VB type) is.
Now, coming to the point: COM Interfaces are passed
a) by reference if the method signature is declared ByVal; b) by a reference to a reference if the method signature is declared ByRef.
For example, the following VB procedure signature: |
maps to the following IDL code: |
This means that even if you pass an interface ByVal, you shouldn't to be surprised that, on returning from the method call, one of its properties have been changed. You might wonder when ByRef makes the difference: Passing an interface ByRef lets the callee replace the object behind the interface with another object that implements the same interface. Here an example: Say that CFastAnimal and CSlowAnimal both implement the interface IRun. CSomething implements IPrepareToRun, which has two methods : PrepareByRef and PrepareByVal: |
Click here to copy the following block | Public Sub PrepareByRef(ByRef a1 As IRun) Set a1 = CreateObject("CSlowAnimal") a1.name = "AAA" End Sub
Public Sub PrepareByVal(ByVal a1 As IRun) Set a1 = Createobject("CSlowAnimal") a1.name = "AAA" End Sub |
Click here to copy the following block | Sub a() Dim x As IRun Set x = CreateObject("CFastAnimal") x.name ="BBB" Dim y As IPrepareToRun Set y = CreateObject("CSomething") y.PrepareByRef(x) x.run Debug.Print x.name End Sub
Sub b() Dim x As IRun Set x = CreateObject("CFastAnimal") x.name ="BBB" Dim y As IPrepareToRun Set y = CreateObject("CSomething") y.PrepareByVal(x) x.run Debug.Print x.name End Sub |
You see the same behavior described above if you pass Interfaces in-Apartment or cross-Apartment (Cross Process / Cross Host) if such interface are standard marshaled (Type-Library marshaling). I should stress, however, that passing interfaces across apartment boundaries is considered bad design (especially across hosts): reading or setting a property involves a roundtrip. There are some cases where you may need to pass an interface for a callback, but NEVER use an interface as a method to pass/return data among two objects if you are not sure the two objects and the interface in question will always be in the same apartment.
There is an exception, though: you can do it if the interface implements MBV (Marshaling by value), and , yes, ADO disconnected Recordsets do implement marshaling by value. This means that when the _Recordset interface crosses apartment boundaries the data behind the recordset are copied in the new apartment. If the parameter is declared ByRef, then the data are copied back. But remember: this happens only if the recordset cross apartment boundaries, if it's not the case you get the standard COM behavior.
The conclusions are:
1) you have to know what standard marshaling is to develop distributed application; 2) you have to know when an interface is MBV and be aware that, in such case, your object behaves differently when is passed in-Apartment or inter-Apartment.
|
|
|
|
Submitted By :
Nayan Patel
(Member Since : 5/26/2004 12:23:06 PM)
|
|
|
Job Description :
He is the moderator of this site and currently working as an independent consultant. He works with VB.net/ASP.net, SQL Server and other MS technologies. He is MCSD.net, MCDBA and MCSE. In his free time he likes to watch funny movies and doing oil painting. |
View all (893) submissions by this author
(Birth Date : 7/14/1981 ) |
|
|