Windows Reimagined
September 14, 2011Using WCF Services in Synergy .NET Applications
January 11, 2012A customer recently reported a strange problem that they were seeing when attempting to use WCF. The problem seemed to occur when they attempted to call a method in their WCF service, where that method had a parameter used to send a class TO the service, and where that class included the use of Synergy types (a struct field containing alpha data in this case). By the way, these Synergy types were internal within the class; the external interface of the class was totally CLS compliant … but that didn’t seem to matter.
The actual problem was that the customer was seeing was “null reference” exceptions at runtime. The error seemed to occur when the setter methods of the servers data class were being called. Now, in order to understand the cause of the problem, it might help to take a step back and thing about what is happening under the hood in this type of scenario.
When you add a “Service Reference” in a client application, Visual Studio (or the svcutil.exe utility) downloads the WSDL information that defines the service, analyzes it, and then creates local “proxy” classes for the various classes that are required in order to interact with the service. When a client application needs to call a method that accepts an object as a parameter, it instantiates a copy of the local proxy class and passes that object as a parameter to the method. WCF then serializes that data (to XML or some other format suitable for transmission over the wire) and calls the method. On the server, the data is received and then de-serialized back into an instance of the original server-based data class; all of the properties being set to the various values that were received over the wire.
As it turns out, when WCF performs this de-serialization and creates an instance of a server data object to pass to a method, it does so in such a way that the default constructor of the data class is not called. And herein lies the problem.
In Synergy .NET all classes contain an implicit default constructor. This constructor, amongst other things, is responsible for the instantiation of any Synergy types present in the class. But because WCF circumvents this mechanism, the Synergy types are never instantiated, and hence the null reference errors.
Right now a little bit of head-scratching is taking place in development, and I’m sure that at some point soon a proper resolution to this problem will emerge … but in the meantime we need a workaround, which thankfully (thanks Jeff) turns out to be relatively straight forward:
private static myConstructor, @System.Reflection.ConstructorInfo
{OnDeserializing}
public method OnDeserializing, void
context, StreamingContext
proc
if (myConstructor==^null)
myConstructor = this.GetType().GetConstructor(new Type[0])
myConstructor.Invoke(this, new Object[0])
endmethod
.endregion
This is the code for a method named OnDeserializing, and you will notice that the method is preceded by an attribute named {OnDeserializing}. This attribute will cause the method to be called whenever an instance of the class is created during a de-serialization operation. Within the method, reflection is used to get a handle on the default constructor for the class, which is then explicitly called. The handle to the constructor is stored in a static variable, so that the code that obtains the handle will only execute once, the first time the method executes. The method then explicitly calls the constructor, which in turn instantiates any Synergy types which may be present in the object.
So … for now … if you want to use a Synergy data class as part of a WCF service, and that class will be used for IN or INOUT method parameters, you need to include this section of code in the class.
1 Comment
What a life saver!!!!!!! This seems to still not be fixed in 9.5.3b!