Pavel B.
Pavel B.

Reputation: 875

passing System.Type to generic type

My Problem is this A have a API controler And creating a Single method delete to data from X DbSet properties but the don't have the same Generic paramether. My result is to somehow pass a System.Type to Generic paramether. And my Question is some way to do it?

    var table = TableInfo.GetValue(_context) as DbSet<[here i need pass it]>;

I need to do something like (I know this can't work)

    var table = TableInfo.GetValue(_context) as DbSet<TableInfo.GetType>;

My full code

    [HttpDelete("{name}/{id}")]
    [Route("api/Delete")]
    public IActionResult Delete(string name = "Items", int id = 2)
    {
        PropertyInfo TableInfo = GetValueByName(name);
        if (TableInfo == null)
            return NotFound("Haaaah");

        var table = TableInfo.GetValue(_context) as DbSet<[here i need pass it]>;
        if (table == null)
            return BadRequest();

        var prop = table.SingleOrDefault(p => p.Id == id);
        if (prop == null)
            return NotFound(prop);

        table.Remove(prop);
        _context.SaveChanges();
        return Ok();
    }

    public PropertyInfo GetValueByName(string name)
    {
        Type t = _context.GetType();
        List<PropertyInfo> list = new List<PropertyInfo>(t.GetProperties());
        foreach(PropertyInfo m in list)
        {
            if (m.Name == name)
                return m;
        }
        return null;
    }

For end sorry about my English. And thanks for all answers :)

Upvotes: 0

Views: 322

Answers (1)

InBetween
InBetween

Reputation: 32740

var table = TableInfo.GetValue(_context) as DbSet<[here i need pass it]>;

You can't do that, you have no compile time information on what type you need, how do you expect to leverage it before the code is even running?

If you really want compile time type information of table you either know the generic type at compile time or you cover all possible execution paths considering all potential generic types your method must handle (horrendous, don't do that).

Using an interface won't work either. A hypothetical IIdEntity and a cast along the lines table as DbSet<IIdEntity> will never work because:

  1. Type variance is only allowed in interfaces and delegates, DbSet is not an interface.
  2. Even if you use IDbSet<TEntity>, this interface is invariant in TEntity so the following will always fail:

    class User: IIdEntity { ... }
    object o = someDbEntityOfUser;
    var db = o as IDbSet<IIdEntity> //will always be null.
    

The best options you have with your current setup are:

  1. Keep using reflection; use it to inspect the Id property of the entities.
  2. Use dynamic and simply let the runtime resolve the Id call.

Upvotes: 1

Related Questions