NGWS SDK Documentation  

This is preliminary documentation and subject to change.
To comment on this topic, please send us email at ngwssdk@microsoft.com. Thanks!

Remoting Object Model Concepts

This section provides guidelines for placing objects in the various class buckets:

Remoting Object Categories

Runtime object types are categorized into 3 categories.

Runtime category Must derive from
Not Marshaled

(Agile)

System.Object
Unbound

(Agile, Marshal By Value)

System.Object

Marked with [serializable]. May have Iserializable & related Constructor

AppDomain-bound

(Agile, Marshal By Reference)

System.MarshalByRefObject
Context-bound

(Contextful, Marshal by Reference)

System.ContextBoundObject

Agile objects

Agile objects are accessed directly from any context and are called directly from the caller context with an AppDomain.

To invoke a method on an agile object from anywhere within an AppDomain, a direct reference would suffice. The Base Class Libraries (System.*) consists mostly of agile classes with a few exceptions.

Unbound (Agile, Marshal By Value) and AppDomain-bound (Agile, Marshal By Reference) are collectively referred to as agile.

“Not Marshaled” type Category

class Foo
{
  int Bar;

  int Foo;

  //. . .
}

class Baz : Foo
{
  //. . .
}

Since Foo is “Not Marshaled” then Baz is also “Not Marshaled”.

Key Points:

Unbound (Object By Value) objects type category

[serializable]
class Foo
{
  int Bar;
  int Foo;

  //. . .
}

class Baz : Foo
{
  //. . .
}

Since Foo is Unbound then Baz is also Unbound.

Key Points:

Marshal By Reference (Object By Reference) object type category

Base class for Remoting objects that need to be marshal by reference. This includes WellKnown SingleCall and WellKnown Singleton WebService objects and Client Activated Objects.

class Zap : MarshalByRefObject
{
  //. . .
}

class Waz : Zap
{
  //. . .
}

Since Zap is AppDomain-Bound then Waz is also AppDomain-Bound.

Key Points:

MarshalByRefObject as the base class for remote objects

Depending on which JIT is being used, certain optimizations may be used for classes which are not Marshaled by Reference e.g. direct field access by JIT. Inlining of methods is another optimization. One of rules of using MarshalByRefObject across AppDomains is that all the parents need to have the ancestor of MarshalByRefObject, this to enable the EE and JIT to provide consistent access.

The incorrect way The correct way
class Foo
{
  int i;
  float f;
  void Method1();
}

[MarshalByRefObject()]
class Baz : Foo
{
  String s;
  void Method2();
}

void SomeCode(Foo foo)
{
  int myInt = foo.i;
  foo.f = 2.4;
  foo.Method1();
}
class Foo : MarshalByRefObject
{
  int i;
  float f;
  void Method1();
}


class Baz : Foo
{
  String s;
  void Method2();
}

void SomeCode(Foo foo)
{
  int myInt = foo.i;
  foo.f = 2.4;
  foo.Method1();
}

Performance Implications for MarshalByRefObject

Since a client may hold a proxy, all operations on the class are appropriately indirected such that the infrastructure can intercept and forward them. This is performed automatically by the EE and JIT working together.

Fields of MarshalByRefObject must be accessed through accessors. This is performed automatically by the EE and JIT working together.

All member functions of MarshalByRefObjects must be called through indirection. This is performed automatically by the EE and JIT working together.

Performance implications of marshalling between AppDomains

Since AppDomains are completely isolated there is no sharing of state, the parameters on the stack must be converted into a binary format (pretty fast) and carried to the other appdomain and turned back into a stack frame. If MarshalByRefObjects are passed in as parameters, these will turn into a proxy in the other appdomain, when the call arrives.

Context Bound Object type category

class Tip : ContextBoundObject
{
  //. . .
}

class Pot : Tip
{
  //. . .
}

Since Tip is Context-Bound then Pot is also Context-Bound.

Key Points: