• 对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);
            }
    }
    

      

     

     

    努力吧少年
  • 相关阅读:
    Ubuntu 开机启动是出现 grub rescue 解决办法
    OpenvSwitch Port Mirror in OpenStack Neutron
    Protobuf 在Ubuntu 14上的编译与使用
    Linux screen 常用命令
    OpenStack/devstack with Neutron on Ubuntu 14 (1)
    osprofiler在openstack Cinder里的使用
    基于SSH协议的端口转发
    HA 技术简介
    Socket Receive数据一次性接收不全的问题
    【转】本文对C#虚函数virtual进行详解。
  • 原文地址:https://www.cnblogs.com/jameswenhe/p/4537988.html
Copyright © 2020-2023  润新知