tags:

views:

112

answers:

5

I think that this problem can be sorted using reflection (a technology which I'm not too sure about).

My code is receiving some code objects that have been serialised to XML at runtime. When I receive it and deserialise it one field is causing me some hassle.

There is a field that can contain a combination of the following data classes (simplified for clarity):

class KeyValuePairType
{
  public string Key;
  public string Value;
}

class KeyValueListPair
{
  public string Key;
  public string[] Value;
}

I receive these into my code as an object[] and I need to determine at runtime what exactly this contains so that I can call an interface on a local object that requires KeyValuePairType[] and KeyValueListPair[] as parameters e.g.

public DoSomeWork(KeyValuePairType[] data1, KeyValueListPair[] data2)

I have the following cases to cope with:

object[] contains:

  1. nothing in which case I call DoSomeWork(null,null);

  2. an array of KeyValuePairType only, in which case I call DoSomeWork(KeyValuePairType[], null);

  3. an array of KeyValueListPair only, in which case I call DoSomework(null, KeyValueListPair[]);

  4. or an array of each, in which case I call DoSomework(KeyValuePairType[], KeyValueListPair[]);

Any ideas are welcome.

Thank you

It turns out that the object array contains a random sequence of discrete objects. Initially I was led to belive that it may be a sequence of discretes and arrays of those objects.

As it is the LINQ statements will cover all eventualities.

Can I say a big thank you to those that that answered. I have posted a +1 for those answering with the LINQ statements.

A: 

It depends, somewhat, on how the individual elements are being handled to you, but in general, the is and as keywords should work fine for checking individual objects in the object[] array, and assigning them to the appropriate output.

Reed Copsey
+5  A: 

Assuming you've got LINQ available to you...

public void Foo(object[] values)
{
    var pairs = values.OfType<KeyValuePairType>().ToArray();
    var lists = values.OfType<KeyValueListPair>().ToArray();

    pairs = pairs.Length == 0 ? null : pairs;
    lists = lists.Length == 0 ? null : lists;

    DoSomeWork(pairs, lists);
}
Jon Skeet
As I understand the question, "values" can contain *arrays* of KeyValuePairType or KeyValueListPair and not simple elements.
bruno conde
That's possible - it's not very clear. If that's the case, are we meant to call DoSomeWork multiple times? OP, please clarify!
Jon Skeet
Initially I wasn't sure myself and was trying to cope with a mix of discrete objects and arrays of those objects. As it turns out its a mix of discrete objects.
ChrisBD
+1  A: 

You can do this using LINQ in C# 3, like this:

void HandleThings(params object[] values) {
    var pairTypes = values.OfType<KeyValuePairType>().ToArray();
    var listPairs = values.OfType<KeyValueListPair>().ToArray();

    DoSomeWork(pairTypes.Any() ? pairTypes : null, listPairs.Any() ? listPairs : null);
}

You can make it a tiny bit faster by replacing .Any() with .Length > 0, at the cost of brevity.

SLaks
A: 

After making sure object[] is not null and has a length of greater than 1, you can just call GetType on the objects in the array.

objectArray[0].GetType().FullName

will return either

"Namespace.KeyValuePairType"

or

"Namespace.KeyValueListPair"
Serhat Özgel
GetType() is almost never the right way of checking appropriate types - and comparing names is appropriate even less often. is/as are your friends, if you need to do it for an individual object. OfType or Cast are appropriate for collections.
Jon Skeet
While it is always good to answer with best practices, I think there is nothing wrong with providing all available solutions. After all, this is more of a learning platform than a production code generating platform.
Serhat Özgel
I disagree. When a solution is inefficient and error-prone, I will downvote it as unsuitable to recommend to someone.
Jon Skeet
+1  A: 

How about this:

object[] objects = GetObjects();

var pairs = objects.OfType<KeyValuePairType[]>().FirstOrDefault();
var lists = objects.OfType<KeyValueListPair[]>().FirstOrDefault();

DoSomeWork(pairs, lists);
bruno conde