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>()
我正在将 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>()