1

I want to return an Expression.Call that creates a dense MathNet Matrix.

This is the Matrix I want:

Matrix<ContentType>.Build.Dense(Rows,Columns)

ContentType will be int, double or Complex.

But I want to create it using Expression.Call. Here's my current code:

Expression.Call(
            typeof(Matrix<>)
                .MakeGenericType(ContentType)
                .GetProperty("Build")
                .GetMethod("Dense", new[] {typeof(int), typeof(int)}),
            Expression.Constant(Rows), Expression.Constant(Columns));

This however results in a build error:

[CS1955] Non-invocable member 'PropertyInfo.GetMethod' cannot be used like a method.

What am I doing wrong?

Henri
  • 205
  • 1
  • 9

1 Answers1

1

There is GetMethod property on PropertyInfo type, which returns property getter method. You are trying to use this property as a method (invoke it) - hence the compiler error. Instead you should do it like this:

// first get Build static field (it's not a property by the way)
var buildProp = typeof(Matrix<>).MakeGenericType(ContentType)
               .GetField("Build", BindingFlags.Public | BindingFlags.Static);
// then get Dense method reference
var dense = typeof(MatrixBuilder<>).MakeGenericType(ContentType)
               .GetMethod("Dense", new[] { typeof(int), typeof(int) });
// now construct expression call
var call = Expression.Call(
               Expression.Field(null /* because static */, buildProp), 
               dense, 
               Expression.Constant(Rows), 
               Expression.Constant(Columns));
Evk
  • 98,527
  • 8
  • 141
  • 191
  • works! Could you explain to me: how did you know to use MatrixBuilder<> or the BindingFlags? Is there a documentation I simply didn't find? – Henri Jun 22 '17 at 07:33
  • 1
    MatrixBuilder is the type of `Matrix.Build` field. So it's MatrixBuilder type which contains that `Dense` method. As for binding flags - that's just kind of common knowledge, they are used everywhere reflection is used. However in this particular case they are not needed, I just always use them for clarity. If you do just `GetField("Build")` - default flags will be used: `BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public`. Since we need public static field (`Build`) - default flags will work fine. – Evk Jun 22 '17 at 07:38