使用Dapper

时间:2018-03-13 21:36:22

标签: asp.net-core

我的Startup.cs包含40个存储库:

services.AddScoped<IUserRepository, UserRepository>();
services.AddScoped<IXRepository, XRepository>();
... 40 more lines ...

我试图找到一种方法将这个混乱局限在一条线上,但是我惨遭失败地想到这一点,我有几种方法在界面中没有。有人能提供一些帮助吗?我明白为什么它不起作用,它没有一个具体的存储库,但我没有接近使这项工作。

InvalidOperationException: Unable to resolve service for type...

// IRepository.cs
public interface IRepository
{
}

// IUserRepository.cs
public interface IUserRepository : IRepository
{
    User ReadToken(string email, string password);
}

// BaseRepository.cs
public class BaseRepository : IDisposable
{
    protected IDbConnection PostgreSQL;

    public BaseRepository(IDbConnection postgreSQL)
    {
        PostgreSQL = postgreSQL;
    }

    public void Dispose()
    {
    }
}

// UserRepository.cs
public class UserRepository : BaseRepository, IUserRepository
{
    public UserRepository(IDbConnection postgreSQL) : base(postgreSQL)
    {
    }

    public User ReadToken(string email, string password)
    {
        object parameters;
        string sql;

        parameters = new
        {
            email,
            password
        };

        sql =
        @"
        SELECT
            user_id AS id,
            token
        FROM users
        WHERE
            email = @email AND
            password = CRYPT(@password, password) AND
            active = TRUE;
        ";

        var user = base.PostgreSQL.Query<User>(sql, parameters).SingleOrDefault();

        if (user == null)
            throw new UnauthorizedException("User", "User not found.");

        return user;
    }
}

// UsersController.cs
public class UsersController : ControllerBase
{
    protected IUserRepository UserRepository;

    public UsersController(IUserRepository userRepository)
    {
        UserRepository = userRepository;
    }
}

// Startup.cs
services.AddTransient<IRepository, BaseRepository>();

2 个答案:

答案 0 :(得分:3)

您要找的是convention based registration。这使您能够注册所有类型,例如以Repository结尾作为它们实现的接口。但是,内置的ASP.NET Core IOC非常轻量级,并且不提供此类功能。因此,您可以使用扫描所有引用程序集的代码将其包装起来,按模式查找类型,然后将它们添加到ServiceCollection,或者您可以使用提供此功能的不同IOC实现并支持.Net Core,例如Autofac,StructureMap等。

答案 1 :(得分:2)

您可以使用Scrutor

执行此操作

它为Microsoft.Extensions.DependencyInjection提供程序集扫描和装饰扩展

所有这些存储库可以总结为这样的东西:

services.Scan(x => x.FromAssemblyOf<IAnAssemblyRegistrationMarker>()
        .AddClasses(filter => filter.AssignableTo(typeof(IRepository)))
        .AsImplementedInterfaces()
        .WithScopedLifetime());

IAnAssemblyRegistrationMarker是一个空接口,指向要扫描的程序集(项目)

AddClasses从所选程序集中添加所有符合

中指定要求的公共非抽象类

AsImplementedInterfaces将每个匹配的具体类型注册为其所有已实现的接口

WithScopedLifetime使用Scoped Lifetime注册每个匹配的具体类型(您还有WithSingletonLifetimeWithTransientLifetime

上面代码示例中的唯一要求是存储库实现IRepository,以便您只定位必要的项目。

免责声明:我与Scrutor无任何关联。我喜欢这件事。