C# 正在管理基本控制器中的ISession。。。

C# 正在管理基本控制器中的ISession。。。,c#,linq-to-sql,asp.net-mvc-2,ninject,C#,Linq To Sql,Asp.net Mvc 2,Ninject,我避免在我的会话中注入每个控制器,从而避免: 我正在尝试访问基本控制器中的IRepository,以便在整个应用程序中使用它。使用下面的第二种方法管理对象的生命周期是否有任何问题?基本上我只想在每次我需要它的时候再创建一次 //正在使用Ninject注入 private readonly IReadOnlySession _repo; public SimpleController(IReadOnlySession repo) { _repo = repo;

我避免在我的会话中注入每个控制器,从而避免:

我正在尝试访问基本控制器中的IRepository,以便在整个应用程序中使用它。使用下面的第二种方法管理对象的生命周期是否有任何问题?基本上我只想在每次我需要它的时候再创建一次

//正在使用Ninject注入

 private readonly IReadOnlySession _repo;
    public SimpleController(IReadOnlySession repo)
    {
        _repo = repo;
    }
//从基本控制器获取->我的首选方法

public abstract class AbstractBaseController : Controller
{
  public AbstractBaseController() { }

 private static IReadOnlyGenericRepository readonlysession;
 public static IReadOnlyGenericRepository ReadOnlySession
 {
   get { return (readonlysession ?? (readonlysession = new ReadOnlyGenericRepository())); }
 }
}
//然后使用

var detail = ReadOnlySession.Single<Cat>(x=> x.CatID== _catid);
使用下面的第二种方法管理对象的生存期是否有问题

使用基本控制器中的这个静态对象,单独对控制器进行单元测试可能有点困难。我也不知道这个
IReadOnlySession
应该代表什么,但是因为它是静态的,所以它将在所有用户=>所有请求之间共享,所以您应该确保它是线程安全的。。。我个人更喜欢通过DI框架注入控制器的存储库方法

使用下面的第二种方法管理对象的生存期是否有问题


使用基本控制器中的这个静态对象,单独对控制器进行单元测试可能有点困难。我也不知道这个
IReadOnlySession
应该代表什么,但是因为它是静态的,所以它将在所有用户=>所有请求之间共享,所以您应该确保它是线程安全的。。。就个人而言,我更喜欢通过DI框架注入控制器的存储库方法。

您还引入了对
ReadOnlyGenericRepository
的固定依赖关系。在我看来,单元测试和实现都很难理解/可读。就我个人而言,我认为这个解决方案给你带来的负面影响比你不必添加一个构造函数参数(这是通过在Resharper中使用简单的Alt-Enter来实现的)所获得的负面影响更多、更糟糕

肯定的:

  • 不需要构造函数参数(或者换一种说法:在Resharper中保存一个Alt-Enter-strike)
否定:

  • 修复对
    ReadOnlyGenericRepository
  • 需要为每个控制器重写testclass
    GetReadOnlySession()
  • 不易理解的单元测试和实现

另外,如果需要传递更多信息给基本构造函数,请考虑聚合而不是继承。

您还为
ReadOnlyGenericRepository
引入了固定的依赖关系。在我看来,单元测试和实现都很难理解/可读。就我个人而言,我认为这个解决方案给你带来的负面影响比你不必添加一个构造函数参数(这是通过在Resharper中使用简单的Alt-Enter来实现的)所获得的负面影响更多、更糟糕

肯定的:

  • 不需要构造函数参数(或者换一种说法:在Resharper中保存一个Alt-Enter-strike)
否定:

  • 修复对
    ReadOnlyGenericRepository
  • 需要为每个控制器重写testclass
    GetReadOnlySession()
  • 不易理解的单元测试和实现

还应考虑聚合而不是继承,以防有更多的内容需要传递给基构造函数。

有没有办法克服这一问题?如何重构?如何使其线程安全?@Haroon,通过使用第一种方法并配置DI框架为每个控制器实例化一个新会话=>基本上将其与HTTP请求绑定。以Ninject为例,您可以在配置容器时使用
.InRequestScope()
???我仍然会将Ninject用于服务,只要它不是存储库…@Haroon,单元测试还不困难,因为您没有_repo属性的setter,这意味着您不能在单元测试中用模拟对象替换它。它将始终使用您在控制器中硬编码的real
ReadOnlyGenericRepository
。另一方面,由于该属性不再是静态的,至少您不会遇到多线程的问题。但是,我不能重写GetReadOnlySession()方法进行测试吗?因此,我提供了自己的具体类,一个实现iRadonlySession的类?这就是我把它变成虚拟的原因???有什么办法克服这个问题吗?如何重构?如何使其线程安全?@Haroon,通过使用第一种方法并配置DI框架为每个控制器实例化一个新会话=>基本上将其与HTTP请求绑定。以Ninject为例,您可以在配置容器时使用
.InRequestScope()
???我仍然会将Ninject用于服务,只要它不是存储库…@Haroon,单元测试还不困难,因为您没有_repo属性的setter,这意味着您不能在单元测试中用模拟对象替换它。它将始终使用您在控制器中硬编码的real
ReadOnlyGenericRepository
。另一方面,由于该属性不再是静态的,至少您不会遇到多线程的问题。但是,我不能重写GetReadOnlySession()方法进行测试吗?因此,我提供了自己的具体类,一个实现iRadonlySession的类?这就是我把它虚拟化的原因???它变得更复杂了。无论如何,是的,存在一个固定的依赖项-但正如您所指出的,您可以重写,因为我有一个抽象的基本控制器-它可以很容易地在一个地方被重写,而不是在其他地方。我们能说它还是不那么容易理解吗???这难道不是开发人员使用组合而不是继承的偏好吗?当我需要多个Inter时,问题就来了
public interface IReadOnlySession
    {
        T Single<T>(System.Linq.Expressions.Expression<Func<T, bool>> expression) where T : class, new();
        System.Linq.IQueryable<T> All<T>() where T : class, new();
    }
private IReadOnlySession readonlysession;
public IReadOnlySession _repo
{
   get { return (readonlysession ?? (readonlysession = GetReadOnlySession())); }
}

protected virtual IReadOnlySession GetReadOnlySession()
{
  return new ReadOnlyGenericRepository();
}