对IOC模式与容器Autofac在MVC里面的一些用法

IOC模式与Autofac的实例

一:对于IOC模式(控制翻转)的简单认识可以去参考秋风的博客,他介绍的容器是Unity,http://www.cnblogs.com/qqlin/archive/2012/10/09/2707075.html

二:下面我介绍一下在项目中对IOC模式与Autofac在MVC中的运用

1:用于我们公司数据库用的是pg,所以相应也使用了NHibernate,如果大家使用的数据库是SQL Server,相当于EF

首先定义数据访问的接口:

 1 public interface IRepository<TEntity> where TEntity : EntityBase
 2     {
 3         object Save(TEntity entity);
 4 
 5         void SaveOrUpdate(TEntity entity);
 6 
 7         IQueryable<TEntity> Query(Expression<Func<TEntity, bool>> predicate = null);
 8 
 9         /*
10         /// <summary>
11         /// default id int, sorted in asc
12         /// </summary>
13         PagedList<TEntity> Query(Expression<Func<TEntity, bool>> predicate, int pageIndex, int pageSize);
14 
15         PagedList<TEntity> QueryDescending(Expression<Func<TEntity, bool>> predicate, int pageIndex, int pageSize);
16          * */
17 
18         /* best practice TId */
19         TEntity Get(object id);
20 
21         TEntity Load(object id);
22 
23         void Update(TEntity entity);
24         void Update(Action<TEntity> action, Expression<Func<TEntity, bool>> predicate = null);
25 
26         void Delete(TEntity entity);
27         void Delete(Expression<Func<TEntity, bool>> predicate = null);
28 
29         IEnumerable<TResult> SqlQuery<TResult>(string sql);
30 
31         int ExecuteSql(string sql);
32     }

2:我们实现这些接口,里面的Session相当于EF里面的上下文

 public class Repository<TEntity> : IRepository<TEntity> where TEntity : EntityBase
    {
        /*
         * 如何自动将操作打包到一个事物中,如Insert update等
         * linq to sql 中有个SubmitChange方法,一次提交之前修改
         * (Injectiont)
         * 
         * 单条sql(一个方法内)的操作很好打包
         * 
         * 不同的Repository使用一个session(One Session per Request),如何保证在一个事物中一同提交,单独的repository可以保证所有操作在一个事务中
         * End Request 提交事务的时候异常 这个怎么处理呢?
         * 
         * 应该单独出一个UnitOfWork,独立于各repository,然后所有的事务操作在其中完成
         * */

        protected ISession Session
        {
            get { return sessionProvider.Session; }
        }

        private readonly ISessionProvider sessionProvider;

        public Repository(ISessionProvider sessionProvider)
        {
            this.sessionProvider = sessionProvider;
        }

        public object Save(TEntity entity)
        {
            return Session.Save(entity);
        }

        public void SaveOrUpdate(TEntity entity)
        {
            Session.SaveOrUpdate(entity);
        }

        /*
        public TEntity Get(Expression<Func<TEntity, bool>> predicate)
        {
            // SingleOrDefault is translated to 'limit 1' by NHibernate
            return Query()
                .Where(predicate)
                .SingleOrDefault();
        }
        * */

        public IQueryable<TEntity> Query(Expression<Func<TEntity, bool>> predicate = null)
        {
            return predicate == null
                ? Session.Query<TEntity>()
                : Session.Query<TEntity>().Where(predicate);
        }

        /*
        public PagedList<TEntity> Query(Expression<Func<TEntity, bool>> predicate, int pageIndex, int pageSize)
        {
            return Query()
                .Where(predicate)
                .OrderBy(entity => entity.Id)
                .ToPagedList(pageIndex, pageSize);
        }

        public PagedList<TEntity> QueryDescending(Expression<Func<TEntity, bool>> predicate, int pageIndex, int pageSize)
        {
            return Query()
                .Where(predicate)
                .OrderByDescending(entity => entity.Id)
                .ToPagedList(pageIndex, pageSize);
        }
        * */

        public TEntity Get(object id)
        {
            return Session.Get<TEntity>(id);
        }

        public TEntity Load(object id)
        {
            return Session.Load<TEntity>(id);
        }

        public void Update(TEntity entity)
        {
            Session.Update(entity);
        }

        public void Update(Action<TEntity> action, Expression<Func<TEntity, bool>> predicate = null)
        {
            var entities = Query(predicate);

            foreach (var entity in entities)
            {
                action(entity);
                Update(entity);
            }
        }

        public void Delete(TEntity entity)
        {
            Session.Delete(entity);
        }

        public void Delete(Expression<Func<TEntity, bool>> predicate = null)
        {
            var entities = Query(predicate);
            entities.ForEach(Delete);
        }

        public IEnumerable<TResult> SqlQuery<TResult>(string sql)
        {
            return Session
                .CreateSQLQuery(sql)
                .SetScalars(typeof (TResult))
                .SetResultTransformer(Transformers.AliasToBean(typeof (TResult)))
                .Future<TResult>();
        }

        public int ExecuteSql(string sql)
        {
            return Session
                .CreateSQLQuery(sql)
                .ExecuteUpdate();
        }

3:现在要真正完成依赖注入就得AtuoFac登场

(1):用builder.RegisterGeneric(typeof (Repository<>)).As(typeof (IRepository<>)).InstancePerRequest()注册或者也可以builder.RegisterType<Object>().As<Iobject>()注册,我使用的是第一种,当然也可以用通过配置的方式使用AutoFac,也不做介绍了

using Autofac;
using WebPrint.Data.Repositories;

namespace WebPrint.Web.Mvc.IoC
{
    public class RepositoriesModule : Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            builder.RegisterGeneric(typeof (Repository<>))
                   .As(typeof (IRepository<>))
                   .InstancePerRequest();
        }
    }
}

 (2)注册你的控制器类,必须的引如Autofac.Integration.Mvc.dll,写在一个公共IOC类中

using System.Web.Http;
using System.Web.Mvc;
using Autofac;
using Autofac.Integration.Mvc;
using Autofac.Integration.WebApi;

namespace WebPrint.Web.Mvc.IoC
{
    public static class IocConfig
    {
        public static void Register(/*params Assembly[] contorllerAssemblies*/)
        {
            var builder = new ContainerBuilder();

            builder.RegisterModule(new RepositoriesModule());

            // register controller
            builder.RegisterControllers(typeof (MvcApplication).Assembly);

            // register api controller
            builder.RegisterApiControllers(typeof (MvcApplication).Assembly);

            // register filters
            // global filters is not working
            builder.RegisterFilterProvider();

            var container = builder.Build();
            // Configure contollers with the dependency resolver
            DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

            // Configure Web API with the dependency resolver
            GlobalConfiguration.Configuration.DependencyResolver = new AutofacWebApiDependencyResolver(container);
        }
    }
}

 (3):到MVCApplication_Start()里面进行注册调用

 protected void Application_Start()
        {
            // Autofac IoC Register
            IocConfig.Register();

            // log4net
            LogConfig.Register();

            //WebApiConfig.Register(GlobalConfiguration.Configuration);
            GlobalConfiguration.Configure(WebApiConfig.Register);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            //路由注册
            RouteConfig.RegisterRoutes(RouteTable.Routes);

            // 去掉Header中mvc版本的描述
            MvcHandler.DisableMvcResponseHeader = true;
            var config = GlobalConfiguration.Configuration;

            config.Formatters.Remove(config.Formatters.XmlFormatter);
            var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();
            jsonFormatter.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
            jsonFormatter.SerializerSettings.ContractResolver = new NHibernateContractResolver();
            jsonFormatter.SerializerSettings.Converters.Add(new StringEnumConverter());

#if DEBUG
            // Start profile
            NHibernateProfiler.StartProfiler();
#endif
        }

  (4):到控制器的构造函数中注入依赖代码

namespace WebPrint.Web.Mvc.Areas.Order.Controllers
{
    [RouteArea("order")]
    [RoutePrefix("catalog")]/*MVC5以上的路由机制*/
    [UserAuthorize(Roles = "OrderCatalog")] /* 权限控制 */
    public class CatalogOrderController : Controller
    {
        private IService<Model.Order> orderService;
        private IService<ImportOrder> importOrderService;

        public CatalogOrderController(IService<Model.Order> orderService, IService<ImportOrder> importOrderService)
        {
            this.orderService = orderService;
            this.importOrderService = importOrderService;
        }
        [Route("{page:int?}")]
        public ActionResult List(string strokeNo, string contractNo,int page = 1)
        {

            ViewBag.StrokeNo = strokeNo;
            ViewBag.ContractNo = contractNo;  

            Expression<Func<ImportOrder, bool>> expr = i => i.Active == 0;

            if (!strokeNo.IsNullOrEmpty())
            {
                expr = expr.And(i => i.StrokeNo.ToUpper().Contains(strokeNo.ToUpper().Trim()));
            }

            if (!contractNo.IsNullOrEmpty())
            {
                expr = expr.And(i => i.ContractNo.ToUpper().Contains(contractNo.ToUpper().Trim()));
            }

            //增加按supply no过滤(vendorCode即supply no)
            var user = userService.Load(UserGroupPermission.CookieUser.Id);
            var isAdmin = user.Groups.Any(o => o.Name == Core.Group.RpacAdmin.ToString());
            var isRegardless = user.VendorCode.Split(';').Contains("*");

            if (!isAdmin && !isRegardless)
            {
                if (!string.IsNullOrEmpty(user.VendorCode) && user.VendorCode.Contains(";"))
                {
                    var supplierSeries = user.VendorCode.Split(';');

                    Expression<Func<ImportOrder, bool>> expr1 = o => o.SupplierSeries.Contains(supplierSeries[0]);
                    supplierSeries.ForEach(o => { expr1 = expr1.Or(or => or.SupplierSeries.Contains(o)); });

                    expr = expr.And(expr1);
                }
                else
                {
                    expr = expr.And(o => o.SupplierSeries.Contains(user.VendorCode));
                }
            }
            //调用
            var model = importOrderService.Queryable(expr).OrderByDescending(o=>o.Id).ToPagedList(page, 15);
            ViewBag.Count = model.Count();

            return View(model);
        }
}

  

 

 

 

posted @ 2015-05-29 11:07  稳稳的河  阅读(438)  评论(2编辑  收藏  举报