当前位置: 首页 > news >正文

专业国外网站建设网站搜索引擎优化的基本内容

专业国外网站建设,网站搜索引擎优化的基本内容,简洁大气公司网站,洛阳恒凯做的网站有哪些《200行代码#xff0c;7个对象——让你了解ASP.NET Core框架的本质》让很多读者对ASP.NET Core管道有了真实的了解。在过去很长一段时间中#xff0c;有很多人私信给我#xff1a;能否按照相同的方式分析一下MVC框架的设计与实现原理#xff0c;希望这篇文章能够满足你们的… 《200行代码7个对象——让你了解ASP.NET Core框架的本质》让很多读者对ASP.NET Core管道有了真实的了解。在过去很长一段时间中有很多人私信给我能否按照相同的方式分析一下MVC框架的设计与实现原理希望这篇文章能够满足你们的需求源代码可以通过原文下载。01IActionResult我们在前面将定义在Controller类型中的Action方法简化成只返回Task或者Void的方法并让方法自身去完成包括对请求予以相应的所有请求处理任务但真实的MVC框架并非如此。真正的MVC框架中具有一个名为IActionResult的重要结构顾名思义IActionResult对象一般会作为Action方法的返回值针对请求的响应任务基本上会由这个对象来实现。作为Action方法执行结果旨在对请求做最终响应的IActionResult接口同样具有极为简单的定义。如下main的代码片段所示IActionResult对象针对请求的响应实现在它唯一的ExecuteResultAsync方法中针对待执行Action的ActionContext上下文是其唯一的输入参数。public interface IActionResult {Task ExecuteResultAsync(ActionContext context); } 针对不同的请求响应需求MVC框架为我们定义了一系列的IActionResult实现类型应用程序同样也可以根据需要定义自己的IActionResult类型。作为演示我们定义了如下这个ContentResult类型它将指定的字符串作为响应主体的内容具体的内容类型媒体内容或者MIME类型则可以灵活指定。public class ContentResult : IActionResult {private readonly string _content;private readonly string _contentType;public ContentResult(string content, string contentType){_content      content;_contentType      contentType;}public Task ExecuteResultAsync(ActionContext context){var response  context.HttpContext.Response;response.ContentType  _contentType;return response.WriteAsync(_content);} } 由于Action方法可能没有返回值为了使Action执行流程执行Action方法将返回值转化成IActionResult对象执行IActionResult对象显得明确而清晰我们定义了如下这个“什么都没做”的NullActionResult类型它利用静态只读属性Instance返回一个单例的NullActionResult对象。public sealed class NullActionResult : IActionResult {private NullActionResult() { }public static NullActionResult Instance { get; }  new NullActionResult();public Task ExecuteResultAsync(ActionContext context)  Task.CompletedTask; }02执行IActionResult对象接下来我们将Action方法返回类型的约束放宽除了Task和VoidAction方法的返回类型还可以是IActionResult、TaskIActionResult和ValueTaskIActionResult。基于这个新的约定我们需要对前面定义的ControllerActionInvoker的InvokeAsync方法作如下的修改。如代码片段所示在执行目标Action方法之后我们调用ToActionResultAsync方法将返回对象转换成一个TaskIActionResult对象最终针对请求的响应只需要直接执行这个IActionResult对象即可。public class ControllerActionInvoker : IActionInvoker {public ActionContext ActionContext { get; }public ControllerActionInvoker(ActionContext actionContext)  ActionContext  actionContext;public async Task InvokeAsync(){var actionDescriptor  (ControllerActionDescriptor)ActionContext.ActionDescriptor;var controllerType  actionDescriptor.ControllerType;var requestServies  ActionContext.HttpContext.RequestServices;var controllerInstance  ActivatorUtilities.CreateInstance(requestServies, controllerType);if (controllerInstance is Controller controller){controller.ActionContext  ActionContext;}var actionMethod  actionDescriptor.Method;var result  actionMethod.Invoke(controllerInstance, new object[0]);var actionResult  await ToActionResultAsync(result);await actionResult.ExecuteResultAsync(ActionContext);}private async TaskIActionResult ToActionResultAsync(object result){if (result  null){return NullActionResult.Instance;}if (result is TaskIActionResult taskOfActionResult){return await taskOfActionResult;}if (result is ValueTaskIActionResult valueTaskOfActionResult){return await valueTaskOfActionResult;}if (result is IActionResult actionResult){return actionResult;}if (result is Task task){await task;return NullActionResult.Instance;}throw new InvalidOperationException(Action methods return value is invalid.);} } 我们接下来将前面定义的ContentResult引入到演示实例的FoobarController中。如下面的代码片段所示我们将Action方法FooAsync和Bar的返回类型分别替换成TaskIActionResult和IActionResult具体返回的都是一个ContentResult对象。两个ContentResult对象都将同一段HTML片段作为响应的主体内容但是FooAsync方法将内容类型设置成 “text/html” 而Bar方法则将其设置为 “text/plain” 。public class FoobarController : Controller {private static readonly string _html  html headtitleHello/title /head bodypHello World!/p /body /html;[HttpGet(/{foo})]public TaskIActionResult FooAsync(){return Task.FromResultIActionResult(new ContentResult(_html, text/html));}public IActionResult Bar()  new ContentResult(_html, text/plain); } 演示程序启动之后如果采用与前面一样的URL访问定义在FoobarController的两个Action方法我们会在浏览器上得到如下图所示的输出结果。由于FooAsync方法将内容类型设置为 “text/html” 所以浏览器会将返回的内容作为一个HTML文档进行解析但是Bar方法将内容类型设置为 “text/plain” 所以返回的内容会原封不动地输出到浏览器上。03IActionResult类型转化前面的内容对Task方法的返回类型做出了一系列的约束但是我们知道在真正的MVC框架中定义在Controller中的Action方法可以采用任意的类型。为了解决这个问题我们可以考虑Action方法返回的数据对象转换成一个IActionResult对象。我们将类型转换规则定义成通过IActionResultTypeMapper接口表示的服务针对IActionResult的类型转换体现在Convert方法上。值得一提的是Convert方法表示待转换的对象的value参数并不一定是Action方法的返回值而是具体数据对象。如果Action方法的返回值是一个TaskTResult或者ValueTaskTResult对象它们的Result属性返回的参数这个待转换的数据对象。public interface IActionResultTypeMapper {IActionResult Convert(object value, Type returnType); } 简单起见我们定义了如下这个ActionResultTypeMapper类型将作为模拟框架对IActionResultTypeMapper接口的默认实现。如代码片段所示Convert方法将返回个内容类型为“text/plain”的ContentResult对象原始对象字符串描述ToString方法的返回值将作为响应主题的内容。public class ActionResultTypeMapper : IActionResultTypeMapper {public IActionResult Convert(object value, Type returnType) new ContentResult(value.ToString(), text/plain); } 当我们将针对Action方法返回类型的限制去除之后我们的ControllerActionInvoker自然需要作进一步修改。Action方法可能会返回一个TaskTResult或者ValueTaskTResult对象泛型参数TResult可以是任意类型所以我们在ControllerActionInvoker类型定义了如下两个静态方法ConvertFromTaskAsyncTValue和ConvertFromValueTaskAsyncTValue将它们转换成TaskIActionResult对象如果返回的不是一个IActionResult对象作为参数的IActionResultTypeMapper对象将来进行类型转换。我们定义在两个静态只读字段_taskConvertMethod和_valueTaskConvertMethod来保存描述这两个泛型方法的MethodInfo对象。public class ControllerActionInvoker : IActionInvoker {private static readonly MethodInfo _taskConvertMethod;private static readonly MethodInfo _valueTaskConvertMethod;static ControllerActionInvoker(){var bindingFlags  BindingFlags.Instance | BindingFlags.NonPublic| BindingFlags.Static;_taskConvertMethod  typeof(ControllerActionInvoker).GetMethod(nameof(ConvertFromTaskAsync), bindingFlags);_valueTaskConvertMethod  typeof(ControllerActionInvoker).GetMethod(nameof(ConvertFromValueTaskAsync), bindingFlags);}private static async TaskIActionResult ConvertFromTaskAsyncTValue(TaskTValue returnValue, IActionResultTypeMapper mapper){var result  await returnValue;return result is IActionResult actionResult? actionResult: mapper.Convert(result, typeof(TValue));}private static async TaskIActionResult ConvertFromValueTaskAsyncTValue(ValueTaskTValue returnValue, IActionResultTypeMapper mapper){var result  await returnValue;return result is IActionResult actionResult? actionResult: mapper.Convert(result, typeof(TValue));}… } 如下所示的是InvokeAsync方法针对Action的执行。在执行了目标Action方法并得到原始的返回值后我们调用了ToActionResultAsync方法将返回值转换成TaskIActionResult最终通过执行IActionResult对象进而完成所有的请求处理任务。如果返回类型为TaskTResult或者ValueTaskTResult我们会直接采用反射的方式调用ConvertFromTaskAsyncTValue或者ConvertFromValueTaskAsyncTValue方法更好的方式是采用表达式树的方式执行类型转换方法以获得更好的性能。public class ControllerActionInvoker : IActionInvoker {    public async Task InvokeAsync(){var actionDescriptor  (ControllerActionDescriptor)ActionContext.ActionDescriptor;var controllerType  actionDescriptor.ControllerType;var requestServies  ActionContext.HttpContext.RequestServices;var controllerInstance  ActivatorUtilities.CreateInstance(requestServies, controllerType);if (controllerInstance is Controller controller){controller.ActionContext  ActionContext;}var actionMethod  actionDescriptor.Method;var returnValue  actionMethod.Invoke(controllerInstance, new object[0]);var mapper  requestServies.GetRequiredServiceIActionResultTypeMapper();var actionResult  await ToActionResultAsync(returnValue, actionMethod.ReturnType, mapper);await actionResult.ExecuteResultAsync(ActionContext);}private TaskIActionResult ToActionResultAsync(object returnValue, Type returnType, IActionResultTypeMapper mapper){//Nullif (returnValue  null || returnType  typeof(Task) || returnType  typeof(ValueTask)){return Task.FromResult IActionResult  (NullActionResult.Instance);}//IActionResultif (returnValue is IActionResult actionResult){return Task.FromResult(actionResult);}//TaskTResultif (returnType.IsGenericType  returnType.GetGenericTypeDefinition()  typeof(Task)){var declaredType  returnType.GenericTypeArguments.Single();var taskOfResult  _taskConvertMethod.MakeGenericMethod(declaredType).Invoke(null, new object[] { returnValue, mapper });return (TaskIActionResult)taskOfResult;}//ValueTaskTResultif (returnType.IsGenericType  returnType.GetGenericTypeDefinition()  typeof(ValueTask)){var declaredType  returnType.GenericTypeArguments.Single();var valueTaskOfResult  _valueTaskConvertMethod.MakeGenericMethod(declaredType).Invoke(null, new object[] { returnValue, mapper });return (TaskIActionResult)valueTaskOfResult;}return Task.FromResult(mapper.Convert(returnValue, returnType));} } 从上面的代码片段可以看出在进行针对IActionResult的类型转换过程中使用到的IActionResultTypeMapper对象是从针对当前请求的依赖注入容器中提取的所以我们在应用启动之前需要作针对性的服务注册。我们将针对IActionResultTypeMapper的服务注册添加到之前定义的AddMvcControllers扩展方法中。public static class ServiceCollectionExtensions {public static IServiceCollection AddMvcControllers(this IServiceCollection services){return services.AddSingletonIActionDescriptorCollectionProvider, DefaultActionDescriptorCollectionProvider().AddSingletonIActionInvokerFactory, ActionInvokerFactory().AddSingletonIActionDescriptorProvider, ControllerActionDescriptorProvider().AddSingletonControllerActionEndpointDataSource, ControllerActionEndpointDataSource().AddSingletonIActionResultTypeMapper, ActionResultTypeMapper();} } 为了验证模拟框架对Action方法的任意返回类型的支持我们将前面演示实例定义的FoobarController做了如下的修改。如代码片段所示我们在FoobarController类型中定义了四个Action方法它们返回的类型分别为TaskContentResult、ValueTaskContentResult、TaskString、ValueTaskStringContentResult对象的内容和直接返回的字符串都是一段相同的HTML。public class FoobarController : Controller {private static readonly string _html  html headtitleHello/title /head bodypHello World!/p /body /html;[HttpGet(/foo)]public TaskContentResult FooAsync() Task.FromResult(new ContentResult(_html, text/html));[HttpGet(/bar)]public ValueTaskContentResult BarAsync() new ValueTaskContentResult(new ContentResult(_html, text/html));[HttpGet(/baz)]public Taskstring BazAsync()  Task.FromResult(_html);[HttpGet(/qux)]public ValueTaskstring QuxAsync()  new ValueTaskstring(_html); } 我们在上述四个Action方法上通过标注HttpGetAttribute特性将路由模板分别设置为“/foo”、“/bar”、“/baz”和“/qux”所以我们可以采用相应的URL来访问这四个Action方法。下图所示的是这个Action的响应内容在浏览器上的呈现。由于Action方法Baz和Qux返回的是一个字符串按照ActionResultTypeMapper类型提供的转换规则最终返回的将是以此字符串作为响应内容内容类型为 “text/plain” 的ContentResult对象。
http://www.zqtcl.cn/news/487088/

相关文章:

  • 做考试平台的网站网站之前没备案
  • 网站维护要多久时间北京网站优化哪家好
  • 单页推广网站模版网站建设一个购买链接
  • 湖南门户网站设计公司免费自媒体网站
  • 美食网站建设项目预算域名解析站长工具
  • 网站如何备案工信局学网站开发首先学哪些基础
  • 什么网站利于优化河北省建设局网站材料备案
  • 自学装修设计从哪里入手沈阳百度seo
  • 做jsp网站用哪些软件下载如何利用网站赚钱
  • 注册网站域名需要什么湘潭公司做网站
  • 一个网站如何优化企业资质查询平台
  • 模板网站为什么做不了优化山西网络网站建设销售公司
  • 建设什么网站可以赚钱设计本网站是用什么做的
  • 荆州市网站建设策划师
  • 苏州中国建设银行招聘信息网站中国企业登记网
  • 网站服务器的重要性新闻软文范例大全
  • 茶叶网站建设一般的风格加大志愿服务网站建设
  • 湖州医院网站建设方案网页游戏知乎
  • 以网站建设为开题报告临海门户网站住房和城乡建设规划局
  • 河南省大型项目建设办公室网站wordpress置顶功能
  • 奉化网站建设三合一网站建设多少钱
  • wordpress文章页怎么调用网站图片wordpress菜单锚点定位
  • 网站建设运营合作合同网站建设英文合同
  • wordpress chrome插件开发图片式网站利于做优化吗
  • 如何做好品牌网站建设策划app要有网站做基础
  • 横沥网站建设公司wordpress运行php
  • 南皮网站建设价格网络推广这个工作好做吗
  • 长安大学门户网站是谁给做的网站排名logo怎么做
  • 襄樊做网站做网站做网站
  • 百度做网站续费费用网站开发的可行性