学习ASP.NET MVC5的一个轻量级的NinJect框架学习的第二天

  新建一个Abstract文件夹   放置一些抽象的类,如接口
  我们通过该接口就可以得到对应类的相关信息, 不需要去管该数据如何存储,以及存储的位置,这就是存储库模式的本质
 public  interface IbookRepository
    {    /// <summary>
         /// 书模型集合
         /// </summary>
        /*我们通过该接口就可以得到对应类的相关信息,
        而不需要去管该数据如何存储,以及存储的位置,这就是存储库模式的本质。*/
        IQueryable<Book> Books { get; }
    }
  

新建一个Concrete文件夹新建一个EfDbContext类,他派生与Dbcontext,他会为数据库中的每一个表定义一个属性(这里是Books)

DbSet<Book>为Book的实体模型
    /// <summary>
    /// 书的上下文对象
    /// </summary>
   public   class EfDbContext: DbContext
    {
      public DbSet<Book> Books { get; set; }
    }

再创建EfBookRepository存储类库,它实现 IBookRepository 接口,使用了上文创建的 EfDbContext 上下文对象,包含了具体的方法定义

  public class EfIBookRepository :IbookRepository
    {
        private readonly EfDbContext _context = new EfDbContext();

        public IQueryable<Book> Books => _context.Books;
      
    }

再接下来创建一个Entities文件夹


//为Book添加一个特性

 [Table("Book")]
    public class Book
    {
        /// <summary>
        /// 标识
        /// </summary>
        public int Id { get; set; }

        /// <summary>
        /// 名称
        /// </summary>

        public string Name { get; set; }

        /// <summary>
        /// 描述
        /// </summary>
    
        public string Description { get; set; }

        /// <summary>
        /// 价格
        /// </summary>
     
        public decimal Price { get; set; }

        /// <summary>
        /// 分类
        /// </summary>
   
        public string Category { get; set; }
    }

再回到WebUI

新建一个文件夹存放我们自定义的工厂  新建一个NinjectControllerFactory 的类 他继承了DefaultControllerFactory这个控制器工厂的类

在这里面也可以添加自定义的代码,可以改变MVC的默认行为

 public class NinjectControllerFactory: DefaultControllerFactory
    {
        private readonly IKernel _kernel;
        public NinjectControllerFactory()
        {
            _kernel = new StandardKernel();
            AddBindings();
        }
        protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
        {
            return controllerType == null
               ? null
               : (IController)_kernel.Get(controllerType);
        }
        /// <summary>
        /// 添加绑定
        /// 因为我们使用了 Ninject 容器,并且需要对控制器中的构造函数中的参数 IBookRepository 进行解析,
        /// 告诉他将使用哪个对象对该接口进行服务,也就是需要修改之前的 AddBindings 方法
        /// </summary>
        private void AddBindings()
        {

       //这里注意 每添加一个接口这里就要进行绑定  上面是解释
            _kernel.Bind<IbookRepository>().To<EfIBookRepository>();
           // _kernel.Bind<IOrderProcessor>().To<EmailOrderProcessor>();

        }

在这里还要在Global.asax里添加一段代码,告诉 MVC 用新建的类来创建控制器对象


        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            RouteConfig.RegisterRoutes(RouteTable.Routes);

   ///ControllerBuilder这个类动态的生成一个控制器,设置指定的控制器工厂
            ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());
        }

现在要为项目添加控制器,视图了

public class BookController : Controller
    {
        private readonly IbookRepository _bookRepository;
        
        public int PageSize = 5;
        public BookController(IbookRepository bookRepository)
        {
            _bookRepository = bookRepository;
        }
           /// <summary>
           /// 首页显示全部书的信息,并分页
           /// </summary>
           /// <param name="category"></param>
           /// <param name="pageIndex"></param>
           /// <returns></returns>
        public ActionResult Details(string category, int pageIndex = 1)
        {
            var model = new BookDetailsViewModels
            {
                Books =
                    _bookRepository.Books.Where(x => category == null || x.Category == category)
                        .OrderBy(x => x.Id)
                        .Skip((pageIndex - 1) * PageSize)
                        .Take(PageSize),
                CurrentCategory = category,
                PageSize = PageSize,
                PageIndex = pageIndex,
                TotalItems = _bookRepository.Books.Count(x => category == null || x.Category == category)
            };
            return View(model);
        }
    }

@model Wen.BooksStore.WebUI.Models.BookDetailsViewModels

@{
    ViewBag.Title = "Books";
}

<!DOCTYPE html>

@foreach (var item in Model.Books)
{
    Html.RenderPartial("_BookSummary", item);
}
    <div class="pager">
        @Html.PageLinks(Model, x => Url.Action("Details", new { pageIndex = x, category = Model.CurrentCategory }))
    </div>


现在基本可以显示了   接下来就是配置伟大的路由了

  public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

            routes.MapRoute(
              name: "Default",
              url: "{controller}/{action}",
              defaults: new { controller = "Book", action = "Details" }
          );
            routes.MapRoute(
             name: null,
             url: "{controller}/{action}/{category}",
             defaults: new { controller = "Book", action = "Details" }
         );

            routes.MapRoute(
                name: null,
                url: "{controller}/{action}/{category}/{pageIndex}",
                defaults: new { controller = "Book", action = "Details", pageIndex = UrlParameter.Optional }
            );
        }

现在可以显示了 那我就接下来做一个购物车实现购买吧

在Abstract文件夹先添加IOrderProcessor接口

   public interface IOrderProcessor
    {/// <summary>
     /// 处理订单
     /// </summary>
     /// <param name="cart"></param>
     /// <param name="contact"></param>
        void ProcessOrder(Cart cart,Contact contact);
      
    }

并在Concrete文件夹下添加EmailOrderProcessor类并继承IOrderProcessor

 /// <summary>
        /// 处理订单
        /// </summary>
        /// <param name="cart"></param>
        /// <param name="contact"></param>
        public void ProcessOrder(Cart cart, Contact contact)
        {
            if (string.IsNullOrEmpty(contact.Email))
            {
                throw new Exception("Email 不能为空!");
            }

            var sb = new StringBuilder();
            foreach (var item in cart.GetCarItems)
            {
                sb.AppendLine($"《{item.Book.Name}》:{item.Book.Price} * {item.Quantity} = {item.Book.Price * item.Quantity}");
            }

            sb.AppendLine($"总额:{cart.GetCarItems.Sum(x => x.Quantity * x.Book.Price)}");
            sb.AppendLine();
            sb.AppendLine($"联系人:{contact.Name} {contact.Address}");

            //设置发件人,发件人需要与设置的邮件发送服务器的邮箱一致
            var fromAddr = new MailAddress(Sender.Account);
            var message = new MailMessage { From = fromAddr };

            //设置收件人,可添加多个,添加方法与下面的一样
            message.To.Add(contact.Email);
            //设置抄送人
            message.CC.Add(Sender.Account);
            //设置邮件标题
            message.Subject = "您的订单正在出库...";
            //设置邮件内容
            message.Body = sb.ToString();
            //设置邮件发送服务器,服务器根据你使用的邮箱而不同,可以到相应的 邮箱管理后台查看,下面是QQ的

            var client = new SmtpClient("smtp.qq.com", 25)
            {
                Credentials = new NetworkCredential(Sender.Account, Sender.Password),
                EnableSsl = true
            };

            //设置发送人的邮箱账号和密码
            //启用ssl,也就是安全发送
            //发送邮件
            client.Send(message);
        }

接下来在Entitites文件夹下添加Cart购物车实体模型

   
    public   class Cart
    {
        private readonly List<CartItem> _cartitems = new List<CartItem>();
        public IList<CartItem> GetCarItems => _cartitems;

        /// <summary>
        /// 添加书的模型
        /// </summary>
        /// <param name="book"></param>
        /// <param name="quantity"></param>
        public void AddBook(Book book,int quantity)
        {
            if (_cartitems.Count==0)
            {
                _cartitems.Add(new CartItem() { Book = book, Quantity = quantity });
                return;
            }
            var model = _cartitems.FirstOrDefault(x=>x.Book.Id==book.Id);
            if (model==null)
            {
                _cartitems.Add(new CartItem() {Book=book,Quantity=quantity });
                return;
            }
            model.Quantity += quantity;
        }
        /// <summary>   
        /// 移除书的模型
        /// </summary>
        /// <param name="book"></param>
        public void RemoveBook(Book book)
        {
            var model = _cartitems.FirstOrDefault(x=>x.Book.Id==book.Id);
            if (model==null)
            {
                return;
            }
            _cartitems.RemoveAll(x=>x.Book.Id==book.Id);
        }
        /// <summary>
        /// 清空购物车
        /// </summary>
        public void Clear()
        {
            _cartitems.Clear();
        }
        /// <summary>
        /// 统计总额
        /// </summary>
        /// <returns></returns>
        public decimal ComputeTotalValue()
        {
            return _cartitems.Sum(x => x.Book.Price * x.Quantity);
        }
    }

再添加一个购物车项存放添加的书并显示用户添加的

 public   class CartItem
    {
        /// <summary>
        /// 书-+--
        /// </summary>
       public Book Book { get; set; }
        /// <summary>
        /// 数量
        /// </summary>
        public int Quantity { get; set; }
    }

一切都完
现在做添加到购物车吧

 public class CartController : Controller
    {
        private readonly IbookRepository _bookRepository;
        private readonly IOrderProcessor _orderprocessor;
        public CartController(IbookRepository bookRepository,IOrderProcessor orderprocessor)
        {
            _bookRepository = bookRepository;
            _orderprocessor = orderprocessor;

        }
        /// <summary>
        /// 首页
        /// </summary>
        /// <returns></returns>
        public ViewResult Index(string returnUrl)
        {
            return View(new CartViewModels() {

                Cart = GetCart(),
                ReturnUrl=returnUrl


            });
        }
        /// <summary>
        /// 添加到购物车
        /// </summary>
        /// <param name="id"></param>
        /// <param name="returnUrl"></param>
        /// <returns></returns>
        public RedirectToRouteResult AddToCart(int id, string returnUrl)
        {
            var book = _bookRepository.Books.FirstOrDefault(x => x.Id == id);

            if (book != null)
            {
                GetCart().AddBook(book, 1);
            }

            return RedirectToAction("Index", new { returnUrl });
        }
        /// <summary>
        /// 移除书的模型
        /// </summary>
        /// <param name="id"></param>
        /// <param name="returnUrl"></param>
        /// <returns></returns>
        public RedirectToRouteResult RemoveFromCart(int id,string returnUrl)
        {
            var book = _bookRepository.Books.FirstOrDefault(x => x.Id == id);

            if (book != null)
            {
                GetCart().RemoveBook(book);
            }
            return RedirectToAction("Index", new {returnUrl });
        }

        /// <summary>
        /// 获取购物车
        /// </summary>
        /// <returns></returns>

        private Cart GetCart()
        {
            var cart = (Cart)Session["Cart"];
            if (cart != null) return cart;
            cart = new Cart();
            Session["Cart"] = cart;
            return cart;
        }
        /// <summary>
        /// 摘要
        /// </summary>
        /// <returns></returns>
        public PartialViewResult Summary()
        {
            return PartialView(GetCart());
        }

        /// <summary>
        /// 结算
        /// </summary>
        /// <returns></returns>
        public ViewResult Checkout()
        {
            return View(new Contact());
        }

        /// <summary>
        /// 结算
        /// </summary>
        /// <param name="contact"></param>
        /// <returns></returns>
        [HttpPost]
        public ViewResult Checkout(Contact contact)
        {
            if (!ModelState.IsValid)
                return View(contact);

            var cart = GetCart();
            _orderprocessor.ProcessOrder(cart, contact);
            cart.Clear();
            return View("Thanks");
        }
        /// <summary>
        /// 清空购物车
        /// </summary>
        /// <param name="id"></param>
        /// <param name="returnUrl"></param>
        /// <returns></returns>
        public RedirectToRouteResult Clear(string returnUrl)
        {
            GetCart().Clear();
            return RedirectToAction("Index",new {returnUrl });
        }
    }

这里注意的是只添加一个视图就是Index

其他三个页面都添加

 再新建一个视图文件夹Shared

_Layout页面

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
    <link href="~/Contents/Site.css" rel="stylesheet" />
    <script src="~/Scripts/jquery-1.10.2.js"></script>
    <script src="~/Scripts/jquery.validate.js"></script>
    <script src="~/Scripts/jquery.validate.unobtrusive.js"></script>
</head>
<body>
    <div id="header">
        @{ Html.RenderAction("Summary", "Cart");}
        <div class="title">图书商城</div>
    </div>
        <div id="sideBar">
            @{ Html.RenderAction("Sidebar", "Nav"); }
        </div>
        <div>
            @RenderBody()
        </div>
</body>
</html>


_BookSummary页面

@model Wen.BooksStore.Domain.Entitites.Book


<div class="item">
    <h3>@Model.Name</h3>
    @Model.Description
    <h4>@Model.Price.ToString("C")</h4>
    @using (Html.BeginForm("AddToCart", "Cart"))
    {
        var id = Model.Id;
        @Html.HiddenFor(x => id);
        @Html.Hidden("returnUrl", Request.Url.PathAndQuery)

        <input type="submit" value="+ 添加到购物车" />
    }
    <br />
    <hr />
</div>
 最后在Views文件夹下添加_ViewStart页面

@{
    Layout = "~/Views/Shared/_Layout.cshtml";
}
补充一个  书的分类  创建Nav控制器
  public class NavController : Controller
    {
        private readonly IbookRepository _bookRepository;
        public NavController(IbookRepository bookRepository)
        {
            _bookRepository = bookRepository;
        }
        // GET: Nav
 
        public PartialViewResult Sidebar(string category= null)
        {
            ViewBag.CurrentCategory = category;
            var categories = _bookRepository.Books.Select(x=>x.Category).Distinct().OrderBy(x=>x);
            return PartialView(categories);

        }

@model IEnumerable<string>
 

<ul>
    <li>@Html.ActionLink("所有分类","Details","Book")</li>
    @foreach (var item in Model)
    {
        <li>@Html.RouteLink(item, new { controller = "Book", action = "Details", category = item, pageIndex = 1 }, new { @class = item == ViewBag.CurrentCategory ? "selected" : null })</li>

    }
</ul>



    }
最后还有一个重大事,就是整个的样式  在WebUI下新建一个文件夹  Contents  新建一个样式Site

body {
}

#header, #content, #sideBar {
    display: block;
}

#header {
    background-color: green;
    border-bottom: 2px solid #111;
    color: White;
}

#header, .title {
    font-size: 1.5em;
    padding: .5em;
}

#sideBar {
    float: left;
    8em;
    padding: .3em;
}

#content {
    border-left: 2px solid gray;
    margin-left: 10em;
    padding: 1em;
}

.pager {
    text-align: right;
    padding: .5em 0 0 0;
    margin-top: 1em;
}

    .pager A {
        font-size: 1.1em;
        color: #666;
        padding: 0 .4em 0 .4em;
    }

        .pager A:hover {
            background-color: Silver;
        }

        .pager A.selected {
            background-color: #353535;
            color: White;
        }

.item input {
    float: right;
    color: White;
    background-color: green;
}

.table {
    100%;
    padding: 0;
    margin: 0;
}

    .table th {
        font: bold 12px "Trebuchet MS", Verdana, Arial, Helvetica, sans-serif;
        color: #4f6b72;
        border-right: 1px solid #C1DAD7;
        border-bottom: 1px solid #C1DAD7;
        border-top: 1px solid #C1DAD7;
        letter-spacing: 2px;
        text-transform: uppercase;
        text-align: left;
        padding: 6px 6px 6px 12px;
        background: #CAE8EA no-repeat;
    }

    .table td {
        border-right: 1px solid #C1DAD7;
        border-bottom: 1px solid #C1DAD7;
        background: #fff;
        font-size: 14px;
        padding: 6px 6px 6px 12px;
        color: #4f6b72;
    }

        .table td.alt {
            background: #F5FAFA;
            color: #797268;
        }

    .table th.spec, td.spec {
        border-left: 1px solid #C1DAD7;
    }

.bookSummary {
    15%;
    float: right;
    margin-top: 1.5%;
}

.error {
    color: red;
}

最后大搞成了

最后总结一下,Ninject是一个IOC容器用来解决程序中组件的耦合问题,它的目的在于做到最少配置。

其他的的IOC工具过于依赖配置文件,需要使用assembly-qualified名称来进行定义,庸长且复杂常常因为打错字而破坏程序,虽然不是很懂,

但是我会一直继续摸索下去



原文地址:https://www.cnblogs.com/pang572936554/p/6759495.html