views:

625

answers:

4

What is the best way of supporting optional data passed to a C# function?

I have web service function in .Net which defines 5 arguments:

[WebMethod]
    public string UploadFile( string wsURL
        , byte[] incomingArray
        , string FileName
        , string RecordTypeName
        , MetaData[] metaDataArray)

The code of this function is not too long (but not trivial either) and there is only one place in the the function where I perform this test if there is any MetaData[] to be processed:

        if (metaDataArray.Length > 0)
        {
            Update update = BuildMetaData(metaDataArray);
            treq2.Items = new Operation[] { sru, cin, update, fetch};
        }
        else
        {
            treq2.Items = new Operation[] { sru, cin, fetch};
        }

I needed a quick and dirty version of the above which only takes 4 arguments (i.e. no "Metadata" array as a final argument) so I cloned the whole function and removed the IF-ELSE block refering to metadata. Ugly I know.

[WebMethod]
    public string UploadFileBasic( string wsURL
        , byte[] incomingArray
        , string FileName
        , string RecordTypeName)

Now I want to do things better and I am looking for advice on the best way to support this. I do not want to burden the client program with creating an empty array as a 5th parameter...I want to have my web service functions to be smart enough to handle this optional data. Thanks.

+3  A: 
private static readonly MetaData[] EmptyMetaData = new MetaData[0];

[WebMethod]
public string UploadFile(string wsURL
    , byte[] incomingArray
    , string fileName
    , string recordTypeName)
{
    return UploadFile(wsURL, incomingArray, fileName, recordTypeName, EmptyMetaData)
}
280Z28
A: 
[WebMethod]
    public string UploadFileBasic( string wsURL
        , byte[] incomingArray
        , string FileName
        , string RecordTypeName)
{
    return UploadFile(wsURL, incomingArray, FileName, RecordTypeName, new MetaData[0]);
}

Then the UploadFile method handles everything, but you're able to expose two interfaces depending on what the consumer wants.

Timothy Carter
He wants to avoid the object creation overhead (which probably isn't even measurable). It's easy to include a `private static readonly` class member just for that job, since 0-length arrays are effectively immutable.
280Z28
@280Z28 OP says "I do not want to burden the client program with creating an empty array as a 5th parameter.", this does not burden the client/consuming app.
Timothy Carter
+7  A: 

Change your check in the method that takes 5 arguments to (note, that you should be checking if the value is null anyway).

    if (metaDataArray != null && metaDataArray.Length > 0)
    {
        Update update = BuildMetaData(metaDataArray);
        treq2.Items = new Operation[] { sru, cin, update, fetch };
    }
    else
    {
        treq2.Items = new Operation[] { sru, cin, fetch};
    }

Then, simply have your 4 argument version call the 5 argument version internally with the metaDataArray argument null.

[WebMethod]
public string UploadFileBasic( string wsURL,
                               byte[] incomingArray,
                               string FileName,
                               string RecordTypeName)
{
    return UploadFile( wsUrl, incomingArray, fileName, RecordTypeName, null );
}
tvanfosson
+1 because despite the fact my answer was a clever fit into his existing code, this is the method I would use in my own code.
280Z28
Thank you very much. I see the elegance of function overloading in a new way from your helpful answer.
John Galt
Following this approach has brought up a new problem: http://stackoverflow.com/questions/1160299/how-to-access-a-web-service-with-overloaded-methods
John Galt
Actually, I had a typo. I would use a different method name, but still defer internally to the other implementation. The MessageName idea (from the other question) is intriguing, but I'm not sure what it really buys you that having a different named method doesn't.
tvanfosson
+1  A: 

How about putting all the arguments including the MetaData Array into a single class and use it as argument to the web service:

public class UploadFileAgrument 
{
  public string wsURL;
  public byte[] incomingArray;
  public string FileName;
  public string RecordTypeName;
  public MetaData[] metaDataArray;
}

[WebMethod]
public string UploadFile(UploadFileAgrument fileToUpload)
{
  if(fileToUpload.metaDataArray!=null && metaDataArray.Length > 0)
  {
  }
  else
  {
  }  
}
Vivek
Thank you for an interesting idea. I want to minimize the types that need to be known by the web service and the clients that consume the WS. I think this would be contrary to that goal but it is a neat idea otherwise. thanks.
John Galt