1

The params keyword of C# allows equivalence between Array and parameter-list, does it not?

Sadly, in my implementation, this isn't the case.

private Entities queryType(String entitiesType, params KeyValuePair<String, object>[] values)
{
    addStandardHeaders();
    String query = parsePredicate(values);
    Task<HttpResponseMessage> filterTask = client.GetAsync(client.BaseAddress + RESTapi.ALMentitiesQuery(domain, project, entitiesType, query));
    Task.WaitAny(filterTask);
    //Callback:
    HttpResponseMessage result = filterTask.Result;
    if (result.IsSuccessStatusCode)
    {
        updateCookies(client.BaseAddress+RESTapi.ALMentitiesQuery(domain, project, entitiesType, query));
        mainHeaders.Clear();
        Task<Stream> output = result.Content.ReadAsStreamAsync();
        Task.WaitAny(output);
        //Callback:
        return (Entities)fromJSON(output.Result, typeof(Entities)); 
    }
    else
    {
        util.Exception exception = getException(result);
        throw new HttpException(exception.Title);
    }
}

The delegate:

public delegate Entities SubTypeQuery(String subType, params KeyValuePair<String, object>[] values);

In application:

public List<Run> getRuns()
{
    List<Entity> selection = ((Entities)subTypeSelector.DynamicInvoke(
        ALMObject.Run.entitiesName(),
        (new KeyValuePair<String, object>("testcycle-id", id))
    )).entities.ToList<Entity>();

    List<Run> runSet = new List<Run>();
    foreach (Entity element in selection)
        runSet.Add(new Run(element, subTypeSelector));
    return runSet;
}

At run-time I get a Type-Exception: "Cannot convert KeyValuePair<String, object> to KeyValuePair<String, object>[]". This renders params completely useless. Suggestions?

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
Olivier10178
  • 191
  • 11
  • Please reduce this to a [mcve]. Most of the code you've provided is irrelevant, and you have't told us where the problem is. Using `KeyValuePair` instead of a simpler type also makes this more complicated than it needs to be. (I'd also strongly recommend that you start following .NET naming conventions.) – Jon Skeet Jul 11 '17 at 10:49

3 Answers3

2

The params keyword of C# allows equivalence between Array and parameter-list, does it not?

When the C# (or VB) compiler is involved, yes. Not when you're using reflection.

The problem is that you're invoking the delegate dynamically - with reflection, basically. Reflection code doesn't take any notice of params. You either need to invoke the delegate directly (without DynamicInvoke) or create the array explicitly.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • If the compiler says 'delegate doesn't exist in the current context' what should I do? – Olivier10178 Jul 11 '17 at 11:14
  • @Olivier10178: Without knowing what your code looks like, that doesn't really help. You might want to ask a new question with a [mcve]. – Jon Skeet Jul 11 '17 at 12:19
2

Why are you dynamically invoking? You seem to know the types of all the arguments.

Whats wrong with simply calling the delegate?

List<Entity> selection = ((Entities)subTypeSelector(
    ALMObject.Run.entitiesName(),
    (new KeyValuePair<String, object>("testcycle-id", id))
)).entities.ToList<Entity>();
InBetween
  • 32,319
  • 3
  • 50
  • 90
  • My compiler angers me; it resolves that, and says 'subTypeSelector doesn't exist in this context'. Any other thoughts? @InBetween – Olivier10178 Jul 11 '17 at 11:10
  • 1
    @Olivier10178 That seems to be an unrelated issue to the question at hand and the code you've posted. Try to create a minimal repro and post a new question. – InBetween Jul 11 '17 at 11:14
  • @InBtetween no wait; it says now that it's an uninvocable member. – Olivier10178 Jul 11 '17 at 11:17
  • what type should I reference the delegate as if I want to apply it?? 'Delegate' doesn't seem to work. – Olivier10178 Jul 11 '17 at 11:19
  • @Olivier10178 The type of `subTypeSelector` should be `SubTypeQuery`. – InBetween Jul 11 '17 at 11:19
  • `My compiler angers me` - it is odd that when you provided the code to us originally it compiled fine, but now it complains about that line. Did you perhaps change any other parts of the code? – mjwills Jul 11 '17 at 11:32
0

I would suggest changing:

new KeyValuePair<String, object>("testcycle-id", id)

to:

new [] { new KeyValuePair<String, object>("testcycle-id", id) }

See also How do I pass an object array into a method as individual parameters? .

mjwills
  • 23,389
  • 6
  • 40
  • 63
  • And how does that leverage `params` which is what the OP is asking about? If you dynamically invoke you *loose* the flexibility `params` offers. The question here is why he's dynamically invoking instead of invoking directly. – InBetween Jul 11 '17 at 11:05
  • As per Jon Skeet's answer, the OP cannot make use of params in a reflection-based scenario. My answer is merely to show him / her an alternative that he / she might consider using. – mjwills Jul 11 '17 at 11:07