Melody's VSTA Blog

Get the latest and greatest information on VSTA here! Find new samples, workarounds, and inside tips in our downloads and blogs. Get your questions answered quickly in our forums or search our site for a FAQ. We're here to help- just ask.

Non-proxiable Types: A Deeper Look

One of the most common questions we see when someone begins an integration is why can't System.Windows.Forms and objects derived from that class be exposed to add-ins.  Our typical answer is that System.Winows.Forms is not serializable and only serializable objects can pass through (or be exposed through) the proxy layer.  The SDK for the VSTA v 2 CPT Release addresses this issue nicely.  Below is an exert from the section from the SDK, "Remotable and Nonremotable Objects".  For more information see the VSTA v 2 CTP Release SDK.



It is important to remember that an object created in and therefore specific to, an application domain can be called directly from that domain, but something must occur before that object can be available outside its domain. Not every type of object can be efficiently published or consumed across domain boundaries; therefore, you must decide which type of object you want to publish based on the requirements of your application. For the purposes of distributed applications, there are two categories of objects: nonremotable objects and remotable objects.

Nonremotable Objects
Some objects cannot leave their application domain; they are never marshaled because they do not declare a method of serialization. These nonremotable objects are designed for use within the same application domain in which they were created and are always accessed directly from that application domain. Most base classes in the .NET Framework class library are nonremotable objects. Nonremotable objects cannot be copied or represented in another application domain. These objects are accessible only from their original application domain.

Remotable Objects
Remotable objects can be accessed outside their application domain or context using a proxy, or they can be copied and these copies can be passed outside their application domain or context; that is, some remotable objects are passed by reference and some are passed by value.

Remotable objects are objects that function well in a widely-distributed environment. There are two main kinds of remotable objects:

  • Marshal-by-value objects, which are copied and passed from the application domain.
  • Marshal-by-reference objects, for which a proxy is created and used by the client to access the object remotely.


Marshal-By-Value Objects
Marshal-by-value (MBV) objects declare their serialization rules (either by implementing ISerializable to implement their own serialization, or by being marked with SerializableAttribute, which tells the system to serialize the object automatically) but do not extend MarshalByRefObject. The remoting system makes a complete copy of these objects and passes the copy to the calling application domain. Once the copy is in the caller's application domain, calls to the copy go directly to that copy. Further, MBV objects that are passed as arguments are also passed by value. Other than declaring the SerializableAttribute attribute or implementing ISerializable, you do not need to do anything to pass instances of your class by value across application or context boundaries.
MBV objects are also used directly from within the object's original application domain. In this case, because no marshaling takes place, no copy is made and access is efficient.

Create a marshal-by-value type by using the SerializableAttribute unless you are extending a class that already implements ISerializable. In this case, you must implement ISerializable for your type.

The remoting system makes extensive use of serializable objects. A reference to an object in another application domain, represented in the remoting system by the ObjRef class, is itself serializable; it must be possible to copy it exactly and send the copy to a client. In addition, objects that transfer data are often serializable objects. DataSet, for example, extends MarshalByValueComponent, which implements ISerializable.

Remoting User-Defined Exceptions
System-defined exceptions are all marshal-by-value types (they implement the ISerializable interface) that, when thrown by a remote object, is automatically copied to the caller if the remoting configurations permit.

For more information about how to create an exception type that can be thrown by a remote object and caught by a remote caller, see How To: Create an Exception Type That Can be Thrown by Remote Objects

Marshal-By-Reference Objects
Marshal-by-reference (MBR) objects are remotable objects that extend at least System.MarshalByRefObject. Depending on what type of activation has been declared, when a client creates an instance of an MBR object in its own application domain, the .NET remoting infrastructure creates a proxy that represents the MBR object and returns to the caller a reference to that proxy. The client then makes calls on the proxy. .NET remoting marshals those calls to the application domain of the remote object and invokes the call.

If a System.MarshalByRefObject is passed as a parameter, it becomes a proxy in the other application domain when the call arrives. MBR return values and out parameters work in the same way.

You should use MBR objects when the state of the object and any executable functionality should stay in the application domain in which it was created. For example, an object that has an internal field that is an operating system handle should extend System.MarshalByRefObject because the operating system handle would not be meaningful in another application domain, in another process, or on another computer. Sometimes an object can also be prohibitively large; that might work on a robust server, but not when sent over a wire to a 33.6 KBps modem.

Scope of Publication
Different remoting systems have different ways of deciding which members and what type of members can be used remotely. .NET remoting exposes objects to other application domains as though they were local, with the following exceptions:

  • Static members. Static fields and methods are never remoted, and field access is through direct memory. That is, .NET remoting always deals with instance members of some form.
  • Instance fields and accessors. For instance fields and accessor methods, the system inserts a check at runtime to determine whether the object is a proxy. If it is not a proxy, field access is direct. Otherwise, the proxy provides accessors to the caller.
  • Private methods. Private methods cannot be remoted. You cannot wrap and pass a delegate to a private method remotely.
  • Delegates. Delegates are marshal-by-value objects. The object within the delegate can be any type of remotable object — a serializable object, a MarshalByRefObject object, or a ContextBoundObject object. The sole exception is that a delegate to an interface method cannot be successfully remoted. The delegate wraps the implementation of the interface method, requiring the type information of the client to be available to the server.
  • Overriding methods on Object. For performance reasons, the virtual methods on Object always execute locally in the application domain where they are called. Calls to any of the following methods only go to the remote object when these methods have been overridden on the remote object:
    • Equals This virtual method executes remotely if overridden.
    • GetHashCode This method executes locally.
    • ToString This virtual method executes remotely if overridden.
    • Equals (the static version) This method executes locally.
    • MemberwiseClone This method executes locally.

<!--[if !supportLineBreakNewLine]-->
<!--[endif]-->

Published Tuesday, December 11, 2007 1:39 PM by Melody

Comments

Anonymous comments are disabled