使用autofac

时间:2018-06-03 14:01:34

标签: c# generics autofac

我试图通过following this stack让这个工作,但它不适合我。 我有模块

public class ProductsModule : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        RegisterPerDependency(builder);
        RegisterPerRequest(builder);
    }

    private static void RegisterPerDependency(ContainerBuilder builder)
    {
        builder.RegisterType<DatabaseContext>().As<DbContext>().InstancePerDependency();
        builder.RegisterGeneric(typeof(Service<>)).AsSelf().InstancePerDependency();
    }

    private static void RegisterPerRequest(ContainerBuilder builder)
    {
        builder.RegisterGeneric(typeof(DataProvider<>)).AsSelf().InstancePerRequest();
    }
}

我有这项服务:

/// <summary>
///     Generic service for entity framework
/// </summary>
/// <typeparam name="T">An entity model</typeparam>
public class Service<T> : IService<T> where T : class
{
    // Create our private properties
    private readonly DbContext _context;

    private readonly DbSet<T> _dbEntitySet;

    /// <summary>
    ///     Default constructor
    /// </summary>
    /// <param name="context">The database context</param>
    protected Service(DbContext context)
    {
        // Assign our context and entity set
        _context = context ?? throw new ArgumentNullException(nameof(context));
        _dbEntitySet = context.Set<T>();
    }

    /// <summary>
    ///     Gets all the entities
    /// </summary>
    /// <param name="includes">Option includes for eager loading</param>
    /// <returns></returns>
    public IQueryable<T> List(params string[] includes)
    {
        // Create a query
        IQueryable<T> query = _dbEntitySet;

        // For each include, append to our query
        if (includes != null) foreach (var include in includes) query = query.Include(include);

        // Return our query
        return query;
    }

    /// <summary>
    ///     Creates an entity
    /// </summary>
    /// <param name="model"></param>
    public void Create(T model) => _dbEntitySet.Add(model);

    /// <summary>
    ///     Updates an entity
    /// </summary>
    /// <param name="model"></param>
    public void Update(T model) => _context.Entry(model).State = EntityState.Modified;

    /// <summary>
    ///     Removes an entity
    /// </summary>
    /// <param name="model"></param>
    public void Remove(T model) => _dbEntitySet.Remove(model);

    /// <summary>
    ///     Saves the database context changes
    /// </summary>
    /// <returns></returns>
    public async Task SaveChangesAsync()
    {
        try
        {
            // Save the changes to the database
            await _context.SaveChangesAsync();
        }
        catch (DbEntityValidationException ex)
        {
            // Retrieve the error messages as a list of strings.
            var errorMessages = ex.EntityValidationErrors.SelectMany(x => x.ValidationErrors).Select(x => x.ErrorMessage);

            // Join the list to a single string.
            var fullErrorMessage = string.Join("; ", errorMessages);

            // Combine the original exception message with the new one.
            var exceptionMessage = string.Concat(ex.Message, " The validation errors are: ", fullErrorMessage);

            // Throw a new DbEntityValidationException with the improved exception message.
            throw new DbEntityValidationException(exceptionMessage, ex.EntityValidationErrors);
        }
    }

    /// <summary>
    ///     Executes a stored procedure in sql
    /// </summary>
    /// <param name="procedure">The name of the sproc</param>
    /// <param name="parameters">the sql params for the sproc</param>
    /// <returns></returns>
    public DbRawSqlQuery<T> ExecuteProcedure(string procedure, List<SqlParameter> parameters) => _context.Database.SqlQuery<T>($"exec {procedure} {CreateQueryStringFromParams(parameters)}");

    /// <summary>
    ///     Dispose
    /// </summary>
    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    /// <summary>
    ///     Creates the input string to run sprocs in sql with EF by converting the sql params into a nice string
    /// </summary>
    /// <param name="parameters"></param>
    /// <returns></returns>
    private static string CreateQueryStringFromParams(IEnumerable<SqlParameter> parameters)
    {
        var response = "";
        var list = parameters as IList<SqlParameter> ?? parameters.ToList();
        var length = list.Count;

        for (var i = 0; i < length; i++)
        {
            response += $"{list[i].ParameterName}=\"{list[i].Value}\"";
            if (i != length - 1) response += ", ";
        }

        return response;
    }

    /// <summary>
    ///     Disposes of any attached resources
    /// </summary>
    /// <param name="disposing">A boolean indicating whether the object is being disposed</param>
    protected virtual void Dispose(bool disposing)
    {
        // If we are disposing, dispose of our context
        if (disposing) _context.Dispose();
    }
}

然后我创建了提供商

public class DataProvider<T> where T : class
{
    private readonly Service<T> _service;
    public DataProvider(Service<T> service) => _service = service;

    public IQueryable<T> List(params string[] includes) => _service.List(includes);
}

这样注入我的控制器:

/// <summary>
/// Used to get the cameras that are currently available
/// </summary>
public class CameraAvailabilitiesController : AvailabilitiesController<CameraAvailability>
{
    /// <summary>
    /// Default constructor
    /// </summary>
    /// <param name="service"></param>
    public CameraAvailabilitiesController(DataProvider<CameraAvailability> service)
        : base(service)
    { }
}

但是当我尝试运行我的项目并获取相机时,我收到了这个错误:

  

找不到类型'r3plica.Service`1 [[Products.Data.Models.CameraAvailability,Products.Data,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null]]'的可访问构造函数。

有谁知道我做错了什么?

1 个答案:

答案 0 :(得分:3)

protected Service(DbContext context)

- 构造函数应该像这样公开:

public Service(DbContext context)