ASP.NET MVC Autofac 单例

ASP.NET MVC Autofac Singleton

我正在将 autofac 与 ASP.NET MVC 一起使用,使用存储库模式。 我有一个这样的class

 public class IoC : ContainerBuilder
{

    /// <summary>
    /// 
    /// </summary>
    private readonly static IoC _instance = new IoC();

    /// <summary>
    /// 
    /// </summary>
    private static object _lock;

    /// <summary>
    /// 
    /// </summary>
    private IContainer _componentsContainer;

    /// <summary>
    /// 
    /// </summary>
    public static IoC Instance
    {
        get
        {
            return _instance;
        }
    }

    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    public IContainer GetComponentsContainer()
    {
        if (_componentsContainer == null)
        {
            lock (_lock)
            {
                if (_componentsContainer == null)
                    _componentsContainer = this.Build();
            }
        }

        return _componentsContainer;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public T Resolve<T>() where T : class
    {
        return GetComponentsContainer().Resolve<T>();
    }

    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    public ILifetimeScope BeginLifetimeScope()
    {
        return GetComponentsContainer().BeginLifetimeScope();
    }

    /// <summary>
    /// 
    /// </summary>
    private IoC()
    {
        _lock = new object();
        ConfigureDependencies();
    }

    /// <summary>
    /// 
    /// </summary>
    private void ConfigureDependencies()
    {
        //Configure all your depedendencies here!!

        //Database connection
        var connectionString = ConfigurationManager.ConnectionStrings["Pixie"].ConnectionString;
        this.Register(c => new SqlConnection(connectionString)).As<IDbConnection>().InstancePerLifetimeScope();
        //Database Connection OrmLite
        OrmLiteConfig.DialectProvider = SqlServerDialect.Provider;
        //Repository
        this.RegisterType<Repository>().As<IRepository>().InstancePerLifetimeScope();
    }

}

并且在 Global.asax 中的 Application_Start 方法中,我有以下内容

protected void Application_Start()
        {
            //var builder = new ContainerBuilder();
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            // Register your MVC controllers.
             IoC.Instance.RegisterControllers(typeof(MvcApplication).Assembly);
              IoC.Instance.RegisterModelBinders(Assembly.GetExecutingAssembly());
            IoC.Instance.RegisterModelBinderProvider();
            IoC.Instance.RegisterModule<AutofacWebTypesModule>();
            IoC.Instance.RegisterModule<AutofacWebTypesModule>();
            IoC.Instance.RegisterSource(new ViewRegistrationSource());


            var MVCControllersResolver = new AutofacDependencyResolver(IoC.Instance.GetComponentsContainer());
}

我的仓库如下

 public class Repository : DataConnection, IRepository
{
    /// <summary>
    /// 
    /// </summary>
    /// <param name="connection"></param>
    public Repository(IDbConnection connection)
        : base(connection)
    {
    }

    public IDbConnection GetConnection()
    {
        return Connection;
    }

    public IEnumerable<T> Select<T>(Expression<Func<T, bool>> objFunc) where T : new()
    {

        // Orm Lite Version 
        return Connection.Select<T>(objFunc);




       }
}

其中 DataConnection 是这样的 class

public class DataConnection : IDisposable
{
    #region Properties

    /// <summary>
    /// 
    /// </summary>
    private IDbConnection _connection;

    /// <summary>
    /// 
    /// </summary>
    protected IDbConnection Connection
    {
        get
        {
            if (_connection.State != ConnectionState.Open && _connection.State != ConnectionState.Connecting)
                _connection.Open();

            return _connection;
        }
    }

    #endregion

    /// <summary>
    /// 
    /// </summary>
    /// <param name="connection"></param>
    public DataConnection(IDbConnection connection)
    {
        _connection = connection;
    }

    /// <summary>
    /// Close the connection if this is open
    /// </summary>
    public void Dispose()
    {
        if (_connection != null && _connection.State != ConnectionState.Closed)
            _connection.Close();
    }
}

我的控制器是这样初始化的

   public class QueryController : Controller
{
    private IRepository Repository;
    public QueryController(IRepository repository)
    {
        this.Repository = repository;
    }
public ActionResult Index()
    {

        IEnumerable<Product> products = Repository.Select<Product>(q=>q.Id == 1);
        return View(products);
    }
}

这样我就可以初始化存储库和控制器。现在我有以下问题。

我有一个这样的 class(型号)

public class OSADCOL
    {

        public int id { get; set; }
        public Nullable<int> TBLid { get; set; }
        public Nullable<int> LOVid { get; set; }
        public Nullable<int> COLGRPid { get; set; }
        public Nullable<int> TabCOLGRPid { get; set; }
}

这个class通过控制器中的请求从数据库中获取数据

IEnumerable<OSQDCOL> osqdcols = Connection.Select<OSQDCOL>("TBLid = @id", new {id = Id });

IEnumerable<OSQDCOL> osqdcols = Repository.Select<OSQDCOL>("TBLid = @id", new {id = Id });

像这样的数据在我的应用程序中的许多控制器中都在使用,并且只是只读的。有没有办法在应用程序启动时初始化这些对象,而不是为每个需要此数据的 HTTP 请求对数据库发出新请求?可能需要单例模式,但我不知道如何使用 autofac 来实现它。 有什么想法吗?

如果您的 "Connection" 在应用程序启动期间可用并且 "Id" 参数始终固定,您可以使用以下行:

像这样声明一个接口:

public interface IOsqlcols : IEnumerable<OSQDCOL>
{}

在注册过程中,您必须像这样注册您的界面:

var rows = Connection.Select<OSQDCOL>("TBLid = @id", new {id = Id });
IoC.Instance.RegisterInstance(rows).As<IOsqlcols>();

然后,你可以在控制器的参数中解析你的接口

public MyController(IOsqlcols osqlcols)
{
    this.osqlcols = osqlcols;
}

顺便说一下,从我的角度来看,我不会尝试用我自己的 class 覆盖 ContainerBuilder。照原样使用。

注册一个委托,解析里面的连接。这将延迟查询直到第一次解析。在您的控制器中,您只需添加 List。如果每个请求需要执行一次并且您不希望它一直存在,请将 .SingleInstance() 更改为 .InstancePerHttpRequest()

IoC.Instance.Register(c =>
{
   var conn = c.Resolve<Connection>();
   return conn.Select<OSQDCOL>("TBLid = @id", new {id = Id }).ToList();
}).As<List<OSQDCOL>>().SingleInstance();

public QueryController(IRepository repository, List<OSQDCOL> myCachedData)
{

}

您也可以像这样设置 CacheService:

builder.Register<CacheService>()
  .SingleInstance()
  .OnActivated(x => x.Instance.InitCache())
  .AutoActivate()
  .As<ICacheService>()