简体   繁体   中英

How to Inject Generic Repository(Or Business Logic Layer) Into ViewModel

For simplicity sake, I'd like to Inject a generic repository into a view model. I'm add the the ViewModel and Repository to the services collection and the ViewModel depends on the Repository. From what I've read, the ViewModel's constructor parameters should be resolved automatically, since it's using IConfiguration. I've tried explicitly instantiating the ViewModel in the Services , but still get the same runtime error and seems to defeat the purpose as I'm creating another instance of the repository.

Repository/IRepository look like this

    public class Repository<TPoco, TDatabaseConnection> : IRepository<TPoco, TDatabaseConnection>
            where TPoco : class
            where TDatabaseConnection : IDbConnection, new()
    {

        public Repository(IConfiguration configuration, string connectionName = "DefaultConnection" )//SqlConnectionConfiguration configuration) //(string connectionString)
        {
            _connectionString = configuration.GetConnectionString(connectionName);
            _configuration = configuration;
        }


...

View Model

    public class PersonViewModel
    {
        private IRepository<Person, IDbConnection> _PersonRepository;

        public List<Person> Persons { get; set; }

        public PersonViewModel(IRepository<Person, IDbConnection> personRepository)
        {
            _PersonRepository=personRepository;
        }
...

In Startup.cs file I add the services like so:

    services.AddScoped<IRepository<Person, SQLiteConnection>, Repository<Person, SQLiteConnection>>();
    services.AddScoped<PersonViewModel>();  //runtime errors here

I'm getting two runtime errors ( System.AggregateException )


Inner Exception 1:
InvalidOperationException: Error while validating the service descriptor 'ServiceType: BlazorInjection.ViewModels.PersonViewModel Lifetime: Scoped ImplementationType: BlazorInjection.ViewModels.PersonViewModel': Unable to resolve service for type 'DapperRepository.IRepository`2[BlazorInjection.Models.Person,System.Data.IDbConnection]' while attempting to activate 'BlazorInjection.ViewModels.PersonViewModel'.

Inner Exception 2:
InvalidOperationException: Unable to resolve service for type 'DapperRepository.IRepository`2[BlazorInjection.Models.Person,System.Data.IDbConnection]' while attempting to activate 'BlazorInjection.ViewModels.PersonViewModel'.

Am I missing a concept? How do I correct this?

change class structure to:

public class PersonViewModel
{
    private IRepository<Person> _PersonRepository;

    public List<Person> Persons { get; set; }

    public PersonViewModel(IRepository<Person> personRepository)
    {
        _PersonRepository = personRepository;
    }
}

public interface IDbConnection
{

}

public class Person { }


public interface IRepository<TPoco> { }

public class SQLiteConnection : IDbConnection 
{
    private string _connectionString;
    private IConfiguration _configuration;

    public SQLiteConnection(IConfiguration configuration, string connectionStringName)
    {
        _connectionString = configuration.GetConnectionString(connectionStringName);
        _configuration = configuration;
    }
}

public class Repository<TPoco> : IRepository<TPoco>
    where TPoco : class
{
    public IDbConnection Connection { get; }

    public Repository(IDbConnection connection)
    {
        Connection = connection;
    }
}

And than in Startup.cs simply change to

services.AddScoped<IDbConnection>(sp => ActivatorUtilities.CreateInstance<SQLiteConnection>(sp, "defaultConnectionStringName"));
        services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
        services.AddScoped<PersonViewModel>();

Notice generic repository registration which makes it easy to extend your data layer. ActivatorUtilities allows you to combine current scope container services with custom parameters. This way (one generic, injected connection) is also in my opinion better from the design perspective, as your repository clients do not need to know the underlying database implementation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM