.NET Method Markers

These are some notes on method markers I found in my old blog posts. Sharing here in case someone benefits from this information.

[ServiceContract]

The ServiceContract marker is used to mark .NET interfaces that hold methods that can be called from a client (makes the interface and RPC service). Callback interfaces are defined with this marker by passing in the CallbackContract attribute where IServerCallback is the name of your callback interface.

[ServiceContract(CallbackContract=typeof(IServerCallback)]

[OperationContract]

This marker makes methods in an interface RPC callable. The class that implements this interface will inherit all of the method attributes.

[OperationContract]
[OperationContract(IsOneWay=true)]

[Serializable]

Use this marker to mark a class as serializable. This will cause all member fields to be serialized (using .NET’s IFormatter). [NonSerialized] marks fields with this to opt them out of serialization.

[DataContract]

Marks a class as able to be passed-by-value by WCF. Use [DataMember] to mark class fields that should be serialized and use [IgnoreDataMember] to exclude fields from serialization.

[MethodImpl]

This marker makes sure that all threads accessing this method are synchronized. The result of this is that multiple threads that call this method take turns in doing so (they are synchronized). This ensures that thread related problems do not arise.

[MethodImpl(MethodImplOptions.Synchronized)]

You would mark methods that modify class fields with this marker, though in some cases it is safer to synchronize access to entire object rather than individual class fields as this increases the risk of accidentally creating race conditions1 or deadlocks.

Manual Locks

Using these manual locks is storngly discouraged.

lock(m_iNumOperationsCompleted)

WCF

If you want to be able to pass an object with code around then you have to compile the receiving end with the interface definition of the remote object.

You wouldn’t ever put a DataContract on a code method because that means all clients that have to use it have to be recompiled if the code in that method is changed.

Passing by Reference

WCF does not support passing by reference because it is an OO principle that, when stretched over a network, does not give efficient solutions. If you pass a pointer to an object residing on the server, then the client would receive a reference to the object that allows it query each class field as it is required. This adds more network overhead with issues like TCP header size (minimum of 20 bytes, read this and time required for ACKs to propagate slowing down the process considerably, especially when lots of member fields must be retrieved. When multiple small member fields are retrieved this way, the size of the actual data is insignificant compared to the packet overhead (format info, destination machine, sequence numbers, TTL and so on). The other idsadvantage of passing by refernece is the increased coupling between server code and client code. The initial decision to use good OO principles was done because these principles are proven to work, however, solving a problem in a distributed fashion (i.e. involving a network connection) changes the nature of the problem.

Do what works, not what is theoretically appealing.

Passing by Value

So now that we’ve crapped all over passing by reference… is passing by value any better? Passing objects directly across a network in a distributed application causes a whole bunch of other problems. The first one involves the fact that objects are data and code. How can we pass both to the remote end? Is it even a good idea to pass code between server and client? It’s definitely not good for interoperability and coupling goes through the roof! We are breaking the rules of good object-oriented design. That is why it took so long for RPC to evolve.

Solution? Compile both sides with class Definition

The remote end cannot infer gettersand setter from serialized object data. The only way to make the remote end aware of this is to compile both sides, not only the object interface, but also the source code of the class implementation. This is obviously terrible from a design point of view as we are creating strong coupling between the remote and the server. Change any code and everything needs compiling. In addition to that, this approach is not very language independent either.

Solution. WCF’s Best Effort Deserialization.

WCF will try to shove the deserialized data into the class the remote end is assigning it to. This class must have the same fields as the incoming data. There is an interoperability issue when .NET’s built in types are serialized.

  1. A race condition is a situation that occurs in multithreaded programs where multiple threads are in a race to update a resource (such as a variable). This can create a number of errors such as the lost update problem (one thread overwrites the change another thread made), out-of-date data and creating inconsistent object states (when two threats interleave their updates on related class fields). ↩︎