在无参数构造函数中解析服务会导致存储库

时间:2018-05-14 07:49:15

标签: c# .net linq model-view-controller

我有一个继承RoleProvider的自定义SiteRole类。我在构造函数中注入IUserService,以便进行查询以获取所有角色。

它继续抛出一个错误,SiteRole类需要一个无参数构造函数。所以我最终注入了IUserService:

public SiteRole()
{
    _userService = DependencyResolver.Current.GetService<IUserService>();
}

在类中,我重写了GetRolesForUser函数

public override string[] GetRolesForUser(string nickname)
{
    return new string[] { _userService.GetRoleForUser(nickname) };
}

UserService在UserRepository中调用此LINQ查询(此行抛出System.InvalidOperationException:&#39;由于DbContext已被释放,因此无法完成操作。&#39;)

public string GetRoleForUser(string nickname)
{
    return DbContext.Users.Where(u => u.Nickname == nickname).FirstOrDefault().Role.Name;
}

有关如何解决此问题的任何提示?您不能通过构造函数将依赖项注入RoleProvider,因此我必须使用DependencyResolver.Current.GetService()。

2 个答案:

答案 0 :(得分:0)

看起来您的SiteRole课程的生命周期比注入的IUserService更长。您应该检查它是否真的是问题的根源,并使用您的DI容器API调整注册服务的生命周期。以下是不同容器的一些链接:AutofacNInjectUnitySimple injector

并且,可能会稍微更改您的SiteRole类型 - 使用属性来生成UserService而不是字段,在SiteRole实例化时使用该字段创建唯一的实例。

public SiteRole()
{
    // this field should be removed
    // _userService = DependencyResolver.Current.GetService<IUserService>();
}

// this property should be used instead of field
private IUserService UserService 
{
    get { DependencyResolver.Current.GetService<IUserService>(); }
}

或者用现代语法

private IUserService UserService => DependencyResolver.Current.GetService<IUserService>();

但要小心并检查您是否未获得创建的UserService个实例的不受控制的计数,例如,如果它在DI容器中配置为每次调用的实例。

答案 1 :(得分:0)

我通过这样做解决了这个问题:

virtual Owned<IUserService> ResolveUserService()
=> DependencyResolver.Current.GetService<Owned<IUserService>>();

使用Using语句调用GetRolesForUser方法中的服务:

public override string[] GetRolesForUser(string nickname)
    {
        using(var userService = ResolveUserService())
        {
            return new string[] {userService.Value.GetRoleForUser(nickname) };

        }
    }

在旁注中,DbContext是在RepositoryBase中构建的。我正在为我的项目使用通用存储库模式。

 public abstract class RepositoryBase<T> where T : class
{

    #region properties

    private StoreEntities dataContext;
    private readonly IDbSet<T> dbSet;

    protected IDbFactory DbFactory
    {
        get;
        private set;
    }

    protected StoreEntities DbContext
    {
        get { return dataContext ?? (dataContext = DbFactory.Init()); }
    }

    #endregion

    protected RepositoryBase(IDbFactory dbFactory)
    {
        DbFactory = dbFactory;
        dbSet = DbContext.Set<T>();
    }


    #region Implementation of defaults

    public virtual void Add(T entity)...........

感谢您的帮助!