Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / Interop / October 2004

Tip: Looking for answers? Try searching our database.

Preventing aggregation in a .NET class

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Robert Simpson - 26 Oct 2004 23:01 GMT
Is there any way to mark a .NET interop class as non-aggregatable?  My .NET
classes are being instantiated as aggegatable objects by 3rd party COM
objects, and when they're passed around to my other .NET objects they're
being passed as __ComObject because the Marshaler can't figure out what to do
with them.  When they're instantiated without an outer unknown, they work
fine.  (using VS.NET 2003/2005)

Help!
Robert Jordan - 27 Oct 2004 01:46 GMT
Hi Robert,

> Is there any way to mark a .NET interop class as non-aggregatable?  My .NET
> classes are being instantiated as aggegatable objects by 3rd party COM
> objects, and when they're passed around to my other .NET objects they're
> being passed as __ComObject because the Marshaler can't figure out what to do
> with them.  When they're instantiated without an outer unknown, they work
> fine.  (using VS.NET 2003/2005)

This behavior is by design: the aggregation hides the identity of
your object. The object passed back is not the object that was
created by the runtime.

When the aggregator does "blind aggregation", you may be able to
cast the object to one of its interfaces.

I think the aggregation could be controlled with
System.Runtime.InteropServices.ExtensibleClassFactory.
You have to apply the code on all classes that get eaten by
the COM object.

(Untested)

[ComVisile(true)]
public class A {
  const int CLASS_E_NOAGGREGATION =  unchecked((int)0x80040110);

  static A {
    ExtensibleClassFactory.RegisterObjectCreationCallback(
      new ObjectCreationDelegate(Create));

  }

  static IntPtr Create(IntPtr aggregator) {
    if (aggregator != IntPtr.Zero) {
      // we don't want to be agg*ted
      throw new COMException("", CLASS_E_NOAGGREGATION)
    }
    else {
       // create a new instance and return its CCW
       return Marshal.GetIUnknownForObject(new A());
    }
  }

  public A() {
  }
}

bye
Rob
Robert Simpson - 27 Oct 2004 02:55 GMT
Well, that explains a lot.  I'll try fiddling with your example and see if it
solves my problem.

In my case, the .NET object is an ActiveX control.  The ActiveX Test
Container aggregates it and does indeed do "mostly" blind delegation to the
inner object.  I've tried everything I can think of to get to the inner
object from my other .NET objects without success.  I've implemented
interfaces and queried for them, even made methods that are supposed to
return the class object ... but they invariably return __ComObject, invalid
cast exceptions or NULL when using the "as" keyword.

> Hi Robert,
>
[quoted text clipped - 46 lines]
> bye
> Rob
Robert Simpson - 27 Oct 2004 15:53 GMT
Well, I messed around with that briefly, and after testing and reading the
MSDN documentation on the ExtensibleClassFactory, it was clear that solution
wasn't going to work.

The ExtensibleClassFactory only provides callback functionality for classes
that derive from COM imported classes.  It will not allow you to customize
how your non-COM based .NET class is constructed through COM.

For the record, this is the error message when you try and register the
creation callback:  "Function can only be called from inside the class
constructor of a class derived from a COM imported class"

> Hi Robert,
>
[quoted text clipped - 46 lines]
> bye
> Rob
Robert Jordan - 28 Oct 2004 00:58 GMT
Hi Robert,

> Well, I messed around with that briefly, and after testing and reading the
> MSDN documentation on the ExtensibleClassFactory, it was clear that solution
[quoted text clipped - 7 lines]
> creation callback:  "Function can only be called from inside the class
> constructor of a class derived from a COM imported class"

Sorry, I didn't tested the code. The best part of the documentation
seems to be the exception message :-/

Did you already tried a late-bind call on the returned __ComObject?

Implement a property:

public YourForm Instance {
  get { return this; }
}

Now the late-bind call on the unknown object:

YourForm f = (YourForm) unk.GetType().InvokeMember(
  "Instance",
  BindingFlags.Instance | BindingFlags.GetProperty,
  null,
  unk,
  null
  );

However, this could only work when the IDispatch implementation
of the aggregator would forward this call to the inner
object.

bye
Rob
Robert Simpson - 28 Oct 2004 18:09 GMT
No such luck -- the outer object intercepts IDispatch -- and even if I did
manage to get to the inner dispatch, during the return trip marshaling
process it queries the returned value from that property for IUnknown, which
again grabs the outer unknown and passes it onto me as __ComObject.

> Sorry, I didn't tested the code. The best part of the documentation
> seems to be the exception message :-/
[quoted text clipped - 23 lines]
> bye
> Rob
Robert Simpson - 28 Oct 2004 18:25 GMT
AH HA!  I finally got it!

The trick was to use an interface with a property (as you had suggested) but
instead of returning the object or late-binding invoke to get the object, the
trick is to wrap the object in an ObjectHandle() class and unwrap it on the
receiving side.

Alternatively, I was able to return any MarshalByRef object that then in
turn exposed a property which returned the actual object I was trying to get
in the first place.

> Is there any way to mark a .NET interop class as non-aggregatable?  My .NET
> classes are being instantiated as aggegatable objects by 3rd party COM
[quoted text clipped - 4 lines]
>
> Help!

Rate this thread:







Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.