benjy benjy - 2 months ago 13
C# Question

Attempting to construct a generic type in C# fails with MissingMethodException

I have the following class definition:

public abstract class ControllerBase<T, V> : Controller where T : EntityBase<T> where V : GenericRepository<T>


Then later on in the class I have the following code:

private V _repo;
...
_repo = (V)Activator.CreateInstance(typeof(V), _dbC, _c);


This compiles just fine. I then have a class with the following definition:

public class SecurityRoleController : ControllerBase<SecurityRole, GenericRepository<SecurityRole>>


That also compiles just fine. However, when I try to hit /SecurityRole in my browser, I get an exception that
Constructor on type GenericRepository'1 not found
. (Note that it's actually a backtick in the exception but that breaks SO formatting.) This is despite the fact that
GenericRepository<T>
has a public constructor that works just fine when I try to directly create an instance of the class.

Anyone know how I can properly construct a generic instance of the class?

TIA,

Benjy

EDIT:

Constructor of
GenericRepository
:

public GenericRepository(DbContext dbContext, Context c, string[] includes = null)
{
_dbContext = dbContext;
_c = c;
if (includes != null)
{
_includes = includes;
}
return;
}


And, the types of
_dbC
and
_c
are of
DbContext
and
Context
, the types that the
GenericRepository
requires in its constructor - and yes, I got these from
.GetType().FullName
. Any thoughts?

Answer

Your constructor declares three parameters. But your call to Activator.CreateInstance is only passing two arguments -- it's not passing in a value for the last parameter (which possesses a default value -- string[] includes = null):

_repo = (V)Activator.CreateInstance(typeof(V), _dbC, _c);

CreateInstance requires that all the parameters be specified -- it bases its method-overload resolution algorithm on the arguments you pass and does not take into account the possibility of default parameters. Thus, to fix, just pass in null (the default value) as the last argument:

_repo = (V)Activator.CreateInstance(typeof(V), _dbC, _c, null);