1

I'm trying to retrieving a DbContext DbSet property by its name but I don't know how to handle the generic parameter.

DataSource.Load(IQuerable source) method comes from an external dll and I cannot modify it.

Knowing the property name of my DbSet prop (from an entity framework dbcontext class) I want to use that property value as parameter for DataSource.Load

 public class DataManager
 {

    private MyDbContext _dbContext;

    public DataManager(MyDbContext dbContext)
    {
        _dbContext = dbContext;
    }


    public object Load(string propName)
    {
        var source = _dbContext.GetType().GetProperty(entityName).GetValue(_dbContext, null);

        return DataSourceLoader.Load(source);         
    }

    //DataSourceLoader.Load signature:
    //DataSourceLoader.Load<T>(System.Linq.IQueryable<T>)

Update

To be more clear: DataSourceLoader.Load loads data from an entity set; I don't care of the return type because it will be serialized and sent to a client plugin.

A client plugin requests the data by an ajax call using the entitySet name as parameter. I don't want to have a different method (or a long switch statement) for each entity set I have and statically invoke the DataSource.Load method.

I would like to resolve the entity set to query at runtime

Alex
  • 191
  • 2
  • 10

2 Answers2

3

The way I understand it, the question is how to call a generic method at runtime.

It's possible to do that with reflection by obtaining the generic MethodInfo definition, binding the generic arguments via MakeGenericMethod call and invoking it via Invoke method.

The concrete answer depends on many factors like if the method is static or instance, if the name is unique or not (overloads) etc. You can see more details about that in Select Right Generic Method with Reflection, but in the simplest form it would be something like this:

var elementType = ((IQueryable)source).ElementType;
var loadMethod = typeof(DataSourceLoader).GetMethod("Load")
    .MakeGenericMethod(elementType);
return loadMethod.Invoke(null, new object[] { source });

You can avoid all that complications by utilizing the DLR Fast Dynamic Dispatch and Invocation feature. All you need in this case is a simple cast to dynamic:

return DataSourceLoader.Load((dynamic)source);
Ivan Stoev
  • 195,425
  • 15
  • 312
  • 343
0

You could try with this method:

public object Load(string setName)
{
    var property = _context.GetType().GetProperties()
        .SingleOrDefault(p => p.PropertyType.IsGenericType
                      && p.PropertyType.GetGenericArguments()[0].GetProperty(setName) != null);
    return property.GetValue(_context) ?? throw new ArgumentOutOfRangeException(setName);
}
grmbl
  • 2,514
  • 4
  • 29
  • 54
  • The whole goal is not having to specify the T type in the method signature – Alex Jun 19 '17 at 06:19
  • this is not solving the issue var source = _dbContext.GetType().GetProperty(entityName).GetValue(_dbContext, null); already retrieves already the value in my code, but source is typeof(object) at compile time. I'm trying to cast the value to IQuerable to use it as parameter for DataSource.Load(IQuerable source) method – Alex Jun 19 '17 at 06:37