0

been dealing with Expression Trees the last couple days and found a problem while trying to call nested Expressions with a second parameter. I'm using the following https://github.com/lukemcgregor/LinqExpander

First I was trying to call it as a normal parameter...something like this:

public static Expression<Func<TEntity, TPropertyResult>> XPTO(short myVariable)

and this way I could call my Expression and send my parameter without a problem. But once I call another expression like this inside the first one, it gives an error ("Parameter count mismatch."). So something like this:

ViewModel1

public static Expression<Func<TEntity, TPropertyResult>> XPTO1(short myVariable)
{
  return x => x.navigationProperty.MyVariableProperty== null ? null : new TPropertyResult()
  (
    ViewModel1FieldViewModel2 = x.DataModel2Field1.AsQueryable().Select(RegistryViewModel.XPTO2()).ToList()
  )
}

ViewModel2

public static Expression<Func<TEntity, TPropertyResult>> XPTO2(short myVariable)
{
  return x => x.navigationProperty.MyVariableProperty== null ||
  (
    ViewModel2Field1 = (x.someValue == myVariable) ? true : false
  )
}

[ReplaceWithExpression(MethodName = nameof(XPTO2))]
public static TPropertyResult FromEntity(TEntity entity, short myVariable)
{
  return XPTO2(myVariable).Compile().Invoke(entity);
}

So I decided to give a try to the Func<in T1, in T2, out TResult> signature. So the above code would look like this

ViewModel1

public static Expression<Func<TEntity,short, TPropertyResult>> XPTO1()
{
  return (x, myVariable) => x.navigationProperty.MyVariableProperty== null ? null : new TPropertyResult()
  (
    ViewModel1FieldViewModel2 = x.DataModel2Field1.AsQueryable().Select(RegistryViewModel.XPTO2()).ToList()
  )
}

public static TPropertyResult FromEntity(TEntity entity, short myVariable)
{
  return XPTO1().Compile().Invoke(entity, myVariable);
}

ViewModel2

public static Expression<Func<TEntity, short, TPropertyResult>> XPTO2()
{
  return (x, myVariable) => x.navigationProperty.MyVariableProperty== null ||
  (
    ViewModel2Field1 = (x.someValue == myVariable) ? true : false
  )
}

[ReplaceWithExpression(MethodName = nameof(XPTO2))]
public static TPropertyResult FromEntity(TEntity entity, short myVariable)
{
  return XPTO2().Compile().Invoke(entity, myVariable);
}

And I'm trying to call XPTO1 on my Service like this

var x = _myRepository.MyFunc(servicoId).AsExpandable().Select(ViewModel1.XPTO1(), myVariable).ToQueryString();

Which clearly is wrong since VS gives me the following error, but I can't figure out how to call the Expression like this, but I'm not understanding how this should be done. enter image description here

It's a requisite that myVariable goes into XPTO2. And I would like to do the same with XPTO1 for reusibility since if I send it as a parameter from another Expression (like on the first segment of code) it send a "Parameter count mismatch."

Any guidance on what I'm doing wrong? Pretty new to Expressions so I'm still discovering it. Thanks in advance and let me know if you need any more information.

AimForNuts
  • 81
  • 2
  • 10
  • "It gives an error" is never nearly as useful as a complete copy/paste of the error. It would also really help if you'd provide a [mcve] rather than snippets using types we don't have - trying to reproduce this at the moment would take (each person) quite a while... – Jon Skeet Jul 14 '22 at 08:56
  • So is that a compile-time error, or an exception? If it's an exception, the complete stack trace would be useful instead of just the message. Noting the kind of error in the question is also useful. Basically, ask yourself "Is there anything that would be useful that folks might ask for in terms of clarification?" and include that in the question - ideally in the very first post. – Jon Skeet Jul 14 '22 at 09:26
  • The immediate cause of the error is clear: You are calling `Select` with two arguments - `ViewModel1.XPTO1()` and `myVariable` - whereas it only takes a single argument `selector`. What you are actually trying to accomplish with that call is less clear. – M Kloster Jul 14 '22 at 09:53
  • 1
    `... XPTO(short myVariable)` - it should be method without parameters. – Svyatoslav Danyliv Jul 14 '22 at 12:29

1 Answers1

1

It is not new library which is doing the same thing. I prefer LINQKit.

So if functionality is similar, choose the following:

public static Expression<Func<TEntity, short, TPropertyResult>> XPTO2()
{
    return (x, myVariable) => x.navigationProperty.MyVariableProperty == null ? null : 
        new TPropertyResult
        {
            // provide fields assignments
        };
}

[ReplaceWithExpression(MethodName = nameof(XPTO2))]
public static TPropertyResult FromEntity(TEntity entity, short myVariable)
{
    return XPTO2().Compile().Invoke(entity, myVariable);
}

And use in the following way:

var x = _myRepository.MyFunc(servicoId)
    .AsExpandable()
    .Select(x => ViewModel1.FromEntity(x, myVariable))
    .ToQueryString();
Svyatoslav Danyliv
  • 21,911
  • 3
  • 16
  • 32
  • This answers my question! Thank you. Also I was missing the ReplaceWithExpression on one of my FromEntity methods which prevented to send another variable Marked as answered. I'll take a look into LINKQKit since it has nugets and that would be a better approach. Thanks once again – AimForNuts Jul 14 '22 at 14:26
  • 1
    Check [sample of usage](https://stackoverflow.com/a/72430867/10646316) – Svyatoslav Danyliv Jul 14 '22 at 14:35