• ASP.NET Core 中文文档 第四章 MVC(3.8)视图中的依赖注入


    原文:Dependency injection into views
    作者:Steve Smith
    翻译:姚阿勇(Dr.Yao)
    校对:孟帅洋(书缘)

    ASP.NET Core 支持在视图中使用 依赖注入 。这将有助于提供视图专用的服务,比如本地化或者仅用于填充视图元素的数据。你应该尽量保持控制器和视图间的关注点分离(separation of concerns)。你的视图所显示的大部分数据应该从控制器传入。

    章节:

    查看或下载示例源码

    一个简单的示例

    你可以使用 @inject 指令将服务注入到视图中。可以把 @inject 看作是给你的视图增加一个属性,然后利用依赖注入给这个属性赋值。

    @inject 的语法:
    @inject <type> <name>

    一个使用 @inject 的例子:

    @using System.Threading.Tasks
    @using ViewInjectSample.Model
    @using ViewInjectSample.Model.Services
    @model IEnumerable<ToDoItem>
    @inject StatisticsService StatsService
    <!DOCTYPE html>
    <html>
    <head>
        <title>To Do Items</title>
    </head>
    <body>
        <div>
            <h1>To Do Items</h1>
            <ul>
                <li>Total Items: @StatsService.GetCount()</li>
                <li>Completed: @StatsService.GetCompletedCount()</li>
                <li>Avg. Priority: @StatsService.GetAveragePriority()</li>
            </ul>
            <table>
                <tr>
                    <th>Name</th>
                    <th>Priority</th>
                    <th>Is Done?</th>
                </tr>
                @foreach (var item in Model)
                {
                    <tr>
                        <td>@item.Name</td>
                        <td>@item.Priority</td>
                        <td>@item.IsDone</td>
                    </tr>
                }
            </table>
        </div>
    </body>
    </html>
    

    这个视图显示了一个 ToDoItem 实例的列表和统计概览。概览信息是由注入的服务 StatisticsService 填入的。这个服务是在 Startup.cs 里的 ConfigureServices 方法中被注册到依赖注入项的。

    // For more information on how to configure your application, visit http://go.microsoft.com/fwlink/?LinkID=398940
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();
    
        services.AddTransient<IToDoItemRepository, ToDoItemRepository>();
        services.AddTransient<StatisticsService>();
        services.AddTransient<ProfileOptionsService>();
    

    StatisticsService 对通过仓储读取到的 ToDoItem 数据集执行一些计算。

    using System.Linq;
    using ViewInjectSample.Interfaces;
    
    namespace ViewInjectSample.Model.Services
    {
        public class StatisticsService
        {
            private readonly IToDoItemRepository _toDoItemRepository;
    
            public StatisticsService(IToDoItemRepository toDoItemRepository)
            {
                _toDoItemRepository = toDoItemRepository;
            }
    
            public int GetCount()
            {
                return _toDoItemRepository.List().Count();
            }
    
            public int GetCompletedCount()
            {
                return _toDoItemRepository.List().Count(x => x.IsDone);
            }
    
            public double GetAveragePriority()
            {
                if (_toDoItemRepository.List().Count() == 0)
                {
                    return 0.0;
                }
    
                return _toDoItemRepository.List().Average(x => x.Priority);
            }
        }
    }
    

    示例中的仓储使用的是 in-memory 集合。上面的实现方法(所有对内存数据的操作)不推荐用于大型、远程存储的数据集。

    这个示例通过绑定到视图的模型以及注入到视图的服务来显示数据:

    填充查找数据

    视图注入有助于填充 UI 元素中的选项数据,例如下拉列表。设想一个包括性别、州以及其他选项的用户资料表单。如果通过标准的 MVC 方式渲染这样一个表单,需要控制器为每一组选项都请求数据访问服务,然后将每一组待绑定的选项填充到模型或 ViewBag 中。

    另一种方法则直接将服务注入到视图中以获取这些选项数据。这种方法将控制器需要的代码量减到了最少,把构造视图元素的逻辑移到视图本身中去。用来显示资料编辑表单的控制器 Action 只需要把用户资料实例传给表格就可以了(而不需要传各种选项数据,译注):

    using Microsoft.AspNetCore.Mvc;
    using ViewInjectSample.Model;
    
    namespace ViewInjectSample.Controllers
    {
        public class ProfileController : Controller
        {
            [Route("Profile")]
            public IActionResult Index()
            {
                // TODO: look up profile based on logged-in user
                var profile = new Profile()
                {
                    Name = "Steve",
                    FavColor = "Blue",
                    Gender = "Male",
                    State = new State("Ohio","OH")
                };
                return View(profile);
            }
        }
    }
    

    用来编辑这些选项的 HTML 表单包含选项中的三个下拉列表:

    这些列表是由注入到视图的一个服务填充的:

    @using System.Threading.Tasks
    @using ViewInjectSample.Model.Services
    @model ViewInjectSample.Model.Profile
    @inject ProfileOptionsService Options
    <!DOCTYPE html>
    <html>
    <head>
        <title>Update Profile</title>
    </head>
    <body>
    <div>
        <h1>Update Profile</h1>
        Name: @Html.TextBoxFor(m => m.Name)
        <br/>
        Gender: @Html.DropDownList("Gender",
               Options.ListGenders().Select(g => 
                    new SelectListItem() { Text = g, Value = g }))
        <br/>
    
        State: @Html.DropDownListFor(m => m.State.Code,
               Options.ListStates().Select(s => 
                    new SelectListItem() { Text = s.Name, Value = s.Code}))
        <br />
    
        Fav. Color: @Html.DropDownList("FavColor",
               Options.ListColors().Select(c => 
                    new SelectListItem() { Text = c, Value = c }))
        </div>
    </body>
    </html>
    

    ProfileOptionsService 是一个 UI 层的服务,旨在为这个表单提供所需数据 :

    using System.Collections.Generic;
    
    namespace ViewInjectSample.Model.Services
    {
        public class ProfileOptionsService
        {
            public List<string> ListGenders()
            {
                // keeping this simple
                return new List<string>() {"Female", "Male"};
            }
    
            public List<State> ListStates()
            {
                // a few states from USA
                return new List<State>()
                {
                    new State("Alabama", "AL"),
                    new State("Alaska", "AK"),
                    new State("Ohio", "OH")
                };
            }
    
            public List<string> ListColors()
            {
                return new List<string>() { "Blue","Green","Red","Yellow" };
            }
        }
    }
    

    提示
    不要忘记在 Startup.csConfigureServices 方法中把你想要通过依赖注入请求的类型注册一下。

    重写服务

    除了注入新服务之外,这种技术也可以用来重写之前已经在页面上注入的服务。下图显示了在第一个例子的页面上可用的所有字段:

    如你所见,默认的字段有 HtmlComponentUrl (同样还有我们注入的 StatsService)。假如你想要把默认的 HTML Helpers 替换成你自己的,你可以利用 @inject 轻松实现:

    @using System.Threading.Tasks
    @using ViewInjectSample.Helpers
    @inject MyHtmlHelper Html
    <!DOCTYPE html>
    <html>
    <head>
        <title>My Helper</title>
    </head>
    <body>
        <div>
            Test: @Html.Value
        </div>
    </body>
    </html>
    

    如果你想要扩展已有服务,你只需要在使用这种替换技术的同时,让你自己的服务继承或封装已有实现。

    参考

    返回目录

  • 相关阅读:
    1114 Family Property (25 分)(并查集)
    【专题复习4:Dijkstra】1003、1018、1030、1072、1087、1111
    1133 Splitting A Linked List (25 分)(链表)
    【专题复习5:并查集】1107、1114、1118
    Java Window 下安装 java
    OpenShift4 节点TimeZone修改
    PHP魔术方法
    .NET中的HashSet
    格式化字符串
    Jetpack Compose
  • 原文地址:https://www.cnblogs.com/dotNETCoreSG/p/aspnetcore-4_3_8-dependency-injection.html
Copyright © 2020-2023  润新知