0

As the title states; I have (shown below) an array of a Structure type. But attempting to extract data from it isn't working because it is evaluated as type Object. If it's impossible I'd really love a morphism of this if possible.

    private Entity makeEntity(params KeyValuePair<String, object>[] fields)
    {
        Entity entity = new Entity();

        IEnumerator cons = fields.GetEnumerator();
        Field field;
        Value value;
        while (cons.MoveNext()){
            value = new Value();
                value.value = cons.Current.Value;
            field = new Field();
                field.name = cons.Current.Key;
                field.values.Add(value);
                entity.fields.Add(field);
        }

        return entity;
    }
Olivier10178
  • 191
  • 11
  • I believe if there is a problem, it has something to do with .NET (the 'object' type). – Olivier10178 Jun 28 '17 at 15:39
  • Have you tried casting `cons.Current.Value` to whatever type you need it to be before assigning it to `value.value`? Otherwise I'm not sure I undestrood what you're asking :) – Fabio Lolli Jun 28 '17 at 15:41
  • Explain what you want to do. The title *doesn't* help at all. `params` has a specific syntax which isn't used here. You explicitly say that you want to receive `object` values. What are you trying to do in the first place? Are you trying to pass a `dynamic` type without using `dynamic` ? – Panagiotis Kanavos Jun 28 '17 at 15:42
  • 1
    Also, you can simply use `foreach KeyValuePair keyValuePair in fields)` rather than having to use an enumerator so explicitly, I guess. – Ray Jun 28 '17 at 15:42
  • 1
    Even simpler: `return new Entity {Values=fields.Select(pair=>pair.Value).ToArray(); Fields=fields.Select(pair=>pair.Key).ToArray();};`. Not that I see the point, unless Entity implements DynamicObject ? Why not use a Dictionary then? – Panagiotis Kanavos Jun 28 '17 at 15:45
  • @PanagiotisKanavos values are a member of fields exclusively. I cannot change the model of Entity at all. – Olivier10178 Jun 28 '17 at 15:58

3 Answers3

2

The simplest fix is to change the declared type of cons:

IEnumerator<KeyValuePair<string, object>> cons = ((IEnumerable<KeyValuePair<string, object>>)fields).GetEnumerator();

However you should just use foreach to iterate over the elements instead:

foreach(var kvp in fields)
{
    ...
}
Lee
  • 142,018
  • 20
  • 234
  • 287
0

Why not use an object (or anonymous object) instead?

private Entity makeEntity(object obj)
{
    Entity entity = new Entity();
    foreach(var kvp in new RouteValueDictionary(obj))
    {
      entity.fields.Add(new Field {name=kvp.Key, values={new Value {value=kvp.Value}});
    }

    return entity;
}

Usage is much easier in most cases:

var x = makeEntity(new {Field1=Value1, Field2=Value2, Field3=Value3});
Robert McKee
  • 21,305
  • 1
  • 43
  • 57
  • You can probably even convert this to a single return of a LINQ Select if you want, which would be even shorter, but I'll leave that up to you. Assuming `Entity.fields` is setable. – Robert McKee Jun 28 '17 at 16:34
-2

I think the casting function proposed in

What is the best way to convert an IEnumerator to a generic IEnumerator?

might be the solution you are looking for:

IEnumerator<T> Cast<T>(IEnumerator iterator)
{
    while (iterator.MoveNext())
    {
        yield return (T) iterator.Current;
    }
}

You call it in your code like this:

...
var cons = Cast<KeyValuePair<String, object>>(fields.GetEnumerator());
...
Helmut D
  • 630
  • 6
  • 11
  • @Lee - You may declare it like that, but you must still do the casting, because `fields.GetEnumerator()` gives you the non-generic version. – Helmut D Jun 28 '17 at 16:17
  • 1
    @HelmutD - Surprisingly `fields.GetEnumerator` does only return the non-generic `IEnumerator` interface but you can access it by casting the source array to `IEnumerable` instead of wrapping the enumerator. – Lee Jun 28 '17 at 16:28