I am trying to add generics to my DAL. There's a list of EF entities and their corresponding repositories. These repositories implement a generic interface. I can't figure out how to instantiantiate the repository.
public T Create(T dtoEntity)
{
string entityClassName = dtoEntity.GetType().Name;
string repositoryClassName = entityClassName + "Repository";
try
{
string entityFullName = entitiesNamespace + entityClassName;
IEntityBase entity = (IEntityBase)assembly.CreateInstance(entityFullName)!;
string repositoryFullName = repositoryNamespace + repositoryClassName;
Type myType = Type.GetType("SmartVisionERP.Dal.SqlServer.Master.DataModel.Config_Accounts,SmartVisionERP.Dal.SqlServer.Master")!;
// IEntityBaseRepository<myType> repository = (IEntityBaseRepository<myType>)assembly.CreateInstance(repositoryFullName)!
IEntityBaseRepository<Config_Accounts> repository = (IEntityBaseRepository<Config_Accounts>)assembly.CreateInstance(repositoryFullName)!;
var list = repository.GetList();
}
catch (Exception)
{
throw;
}
return dtoEntity;
}
- I am receiving a dtoEntity, I'm extracting the class name and then build the repository name out of it. For the scenario I am testing, these are "Config_Accounts" and "Config_AccountsRepository".
- I am using reflection to instatiate the EF entity, has the same name, it's located in a different assembly. This line works properly, I have the entity.
- The repository interface expects a T.
IEntityBaseRepository<T> where T : class, IEntityBase, new() - I am getting the correct type in myType variable.
- The commented line fails with the message "myType is a variable but is used as a type".
- As soon as I write Config_Accounts instead of myType, it works, but this defeats the goal, I am trying to pass the actual type there.
I am out of ideas. Could anyone shed some light? How can I pass to that line a type generated from a string, in such way it actually works?
Thank you
========= EDIT =========
Based on help I received I have changed the code to look like below. I got an error stating "cannot instantiate an interface", which makes sense, so I passed the base class instead. I got the repository in an object, but the object does not expose any of the methods defined in the base class. I am assuming those will need to be exposed and used through more reflection, as suggested in one of the answers.
public T Create(T dtoEntity)
{
string entityClassName = dtoEntity.GetType().Name;
string repositoryClassName = entityClassName + "Repository";
try
{
string entityFullName = $"{entitiesNamespace}{entityClassName}";
IEntityBase entity = (IEntityBase)assembly.CreateInstance(entityFullName)!;
Type template = typeof(EntityBaseRepository<>);
Type myType = Type.GetType("SmartVisionERP.Dal.SqlServer.Master.DataModel.Config_Accounts,SmartVisionERP.Dal.SqlServer.Master")!;
Type genericType = template.MakeGenericType(myType);
object instance = Activator.CreateInstance(genericType);
//string repositoryFullName = repositoryNamespace + repositoryClassName;
//IEntityBaseRepository<Config_Accounts> repository = (IEntityBaseRepository<Config_Accounts>)assembly.CreateInstance(repositoryFullName)!;
//var list = repository.GetList();
}
catch (Exception)
{
throw;
}
return dtoEntity;
}