HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Implementing WCF method that supports either string or object as a method parameter

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
methodsupportseitherthatobjectimplementingstringparameterwcf

Problem

I have the following contract in a WCF-based web service:

public List GetAllPossibleQueryEngineHostNames(Instance instance);


Obviously, I can call this and pass in an Instance object. However, I need to also support older versions of the client, which pass in a string like so:

string instance = "value";
svc.GetAllPossibleQueryEngineHostNames(instance);


To do this, I created a WCF behavior. This was new to me, which is why I'd appreciate some code review feedback. Note, right now only de-serialization is supported. Don't worry that WriteObjectContent is not implemented. I'll do that later, if I have the need.

```
public class InstanceSerializer : XmlObjectSerializer
{
const string localName = "instance";

public override bool IsStartObject(XmlDictionaryReader reader)
{
return String.Equals(reader.LocalName, localName, StringComparison.OrdinalIgnoreCase);
}

public override object ReadObject(XmlDictionaryReader reader, bool verifyObjectName)
{
string xml = reader.ReadOuterXml();
XDocument doc = XDocument.Parse(xml);

string shortCode = doc.Descendants()
.Where(e => e.Name.LocalName == "ShortCode")
.Select(e => e.Value)
.FirstOrDefault();

string connStr = doc.Descendants()
.Where(e => e.Name.LocalName == "ConnectionString")
.Select(e => e.Value)
.FirstOrDefault();

if (connStr != null || shortCode != null) // Instance passed as Instance object
{
return new Instance(shortCode, connStr);
}

// Instance passed as String
Instance instance = ((XElement) doc.FirstNode).Value;
return instance;
}

public override void WriteEndObject(XmlDictionaryWriter writer)
{
writer.WriteEndElement();
}

public override void WriteObjectContent(XmlDictionaryWriter writer, object graph)
{
}

public override void WriteStartObject(X

Solution

I think your last method could look a tad cleaner with replacing long type names with var and not doing the null comparison (since dcsob is unused otherwise) and replacing it with a is comparison:

private static void ReplaceSerializerOperationBehavior(ContractDescription contract)
{
    foreach (var od in contract.Operations)
    {
        for (var i = 0; i < od.Behaviors.Count; i++)
        {
            if (od.Behaviors[i] is DataContractSerializerOperationBehavior)
            {
                od.Behaviors[i] = new InstanceBehavior(od);
            }
        }
    }
}

Code Snippets

private static void ReplaceSerializerOperationBehavior(ContractDescription contract)
{
    foreach (var od in contract.Operations)
    {
        for (var i = 0; i < od.Behaviors.Count; i++)
        {
            if (od.Behaviors[i] is DataContractSerializerOperationBehavior)
            {
                od.Behaviors[i] = new InstanceBehavior(od);
            }
        }
    }
}

Context

StackExchange Code Review Q#59722, answer score: 2

Revisions (0)

No revisions yet.