C#.NET 面试题 初级篇(五)
更新: 2023-06-29 18:26:31 字数: 0 字 时长: 0 分钟
如何在 Controller 中注入 Service?
在 ConfigService 方法中配置这个 Service。
在 Controller 的构造函数中,添加这个依赖注入。
ASP.NET Core 比 ASP.NET 更具优势的地方是什么?
1、跨平台,ASP.NET Core 可以运行在 Windows 、Linux 和 MAC 系统上;
2、对框架本安装没有依赖,所有依赖都跟程序本身在一起;
3、ASP.NET Core 处理请求的效率更高,进而可以处理更多的请求;
4、ASP.NET Core 具有更多的安装配置方法。
ASP.NET Core 主要的特性有哪些?
1、依赖注入。
2、日志系统架构。
3、引入了一个跨平台的网络服务器,Kestrel。可以没有 iis, apache 和 nginx 就可以单独运行。
4、可以使用命令行创建应用。
5、使用 appsettings.json 来配置工程。
6、使用 Startup 来注册服务。
7、更好的支持异步编程。
8、支持 Web Socket 和 SignalR。
9、对于跨网站的请求的预防和保护机制。
ASP.NET Core Filter 如何支持依赖注入?
可以通过全局注册,支持依赖注入
通过 TypeFilter(typeof(Filter)) 标记在方法,标记在控制器
通过 ServiceType(typeof(Filter))标记在方法,标记在控制器,必须要注册 Filter 这类;
TypeFilter 和 ServiceType 的本质是实现了一个 IFilterFactory 接口;
Asp.NET Core 中有哪些异常处理的方案?
1、继承 Controller,重写 OnActionExecuted。
默认都会继承一个 Controller 类,重写 OnActionExecuted,添加上异常处理即可。一般情况下我们会新建一个 BaseController, 让所有 Controller 继承 BaseController。
public class BaseController : Controller
{
public override void OnActionExecuted(ActionExecutedContext context)
{
var exception = context.Exception;
if (exception != null)
{
context.ExceptionHandled = true;
context.Result = new ContentResult
{
Content = $"BaseController错误 : { exception.Message }"
};
}
base.OnActionExecuted(context);
}
}
2、使用 ActionFilterAttribute。
ActionFilterAttribute 是一个特性,本身实现了 IActionFilter 及 IResultFilter , 所以不管是 action 里抛错,还是 view 里抛错,理论上都可以捕获。我们新建一个 ExceptionActionFilterAttribute, 重写 OnActionExecuted 及 OnResultExecuted,添加上异常处理
public class ExceptionActionFilterAttribute:ActionFilterAttribute
{
public override void OnActionExecuted(ActionExecutedContext context)
{
var exception = context.Exception;
if (exception != null)
{
context.ExceptionHandled = true;
context.Result = new ContentResult
{
Content = $"错误 : { exception.Message }"
};
}
base.OnActionExecuted(context);
}
public override void OnResultExecuted(ResultExecutedContext context)
{
var exception = context.Exception;
if (exception != null)
{
context.ExceptionHandled = true;
context.HttpContext.Response.WriteAsync($"错误 : {exception.Message}");
}
base.OnResultExecuted(context);
}
}
使用方式有两种, 在 controller 里打上 [TypeFilter(typeof(ExceptionActionFilter)] 标签;
在 Startup 里以 filter 方式全局注入。
services.AddControllersWithViews(options =>
{
options.Filters.Add<ExceptionActionFilterAttribute>();
})
3、使用 IExceptionFilter。
Asp.Net Core 提供了 5 类 filter, IExceptionFilter 是其中之一,顾名思义,这就是用来处理异常的。Asp.net Core 中 ExceptionFilterAttribute 已经实现了 IExceptionFilter,所以我们只需继承 ExceptionFilterAttribute,重写其中方法即可。 同样新建 CustomExceptionFilterAttribute 继承 ExceptionFilterAttribute,重写 OnException ,添加异常处理
public class CustomExceptionFilterAttribute : ExceptionFilterAttribute
{
public override void OnException(ExceptionContext context)
{
context.ExceptionHandled = true;
context.HttpContext.Response.WriteAsync($"CustomExceptionFilterAttribute错误:{context.Exception.Message}");
base.OnException(context);
}
}
4、使用 ExceptionHandler。
在 startup 里,vs 新建的项目会默认加上
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
5、自定义 Middleware 处理。
public class ErrorHandlingMiddleware
{
private readonly RequestDelegate next;
public ErrorHandlingMiddleware(RequestDelegate next)
{
this.next = next;
}
public async Task Invoke(HttpContext context)
{
try
{
await next(context);
}
catch (System.Exception ex)
{
//处理异常
}
}
}
ASP.NET Core 中服务的生命周期?
1、Singleton 单例模式
只有一个服务的实例被创建,这个实例,存储在内存中,可以在整个应用程序中使用。我们可以对一些初始化代价比较大的服务,使用 Singleton 模式。在代码中可以这样:
services.AddSingleton<IProductService, ProductService>();
2、Scoped 作用域
这种模式下,将会为每一个请求,都创建一个服务的实例。所有同一个请求中的中间件、MVC 控制器,等等,都会得到一个相同的服务实例。Entity Framework Context 就是一个 Scoped 服务最好的参考例子。我们可以通过使用 AddScoped 方法来使用 Scoped 模式:
services.AddScoped<IProductService, ProductService>();
3、Transient 短暂的、瞬变的
Transient 模式下,服务每次被请求的时候,都会创建一个服务实例,这种模式特别适合轻量级、无状态的服务。我们可以使用 AddTransient 方法,来注入服务:
services.AddTransient<IProductService, ProductService>();
ASP.NET Core 里面的路径是如何处理的?
路径处理是用来为进入的请求寻找处理函数的机制。所有的路径在函数运行开始时进行注册。
主要有两种路径处理方式, 常规路径处理和属性路径处理。常规路径处理就是用 MapRoute 的方式设定调用路径,属性路径处理是指在调用函数的上方设定一个路径属性。
什么是依赖注入?
依赖注入是一个过程,就是当一个类需要调用另一个类来完成某项任务的时候,在调用类里面不要去 new 被调用的类的对象,而是通过注入的方式来获取这样一个对象。具体的实现就是在调用类里面有一个被调用类的接口,然后通过调用接口的函数来完成任务。比如 A 调用 B,而 B 实现了接口 C,那么在 A 里面用 C 定义一个变量 D,这个变量的实例不在 A 里面创建,而是通过 A 的上下文来获取。这样做的好处就是将类 A 和 B 分开了,他们之间靠接口 C 来联系,从而实现对接口编程。
依赖注入有哪几种方式?
setter注入
就是在类 A 里面定义一个 C 接口的属性 D,在 A 的上下文通过 B 实例化一个对象,然后将这个对象赋值给属性 D。主要就是 set 与 get
构造函数注入
就是在创建 A 的对象的时候,通过参数将 B 的对象传入到 A 中。 还有常用的注入方式就是工厂模式的应用了,这些都可以将 B 的实例化放到 A 外面,从而让 A 和 B 没有关系。还有一个接口注入,就是在客户类(A)的接口中有一个服务类(B)的属性。在实例化了这个接口的子类后,对这个属性赋值,这和 setter 注入一样。
接口注入
相比构造函数注入和属性注入,接口注入显得有些复杂,使用也不常见。具体思路是先定义一个接口,包含一个设置依赖的方法。然后依赖类,继承并实现这个接口。
依赖注入有哪些著名的框架?
Unity、Autofac、Spring.Net、MEF、Injection、Asp.Net Core 的 ServiceCollection。
控制反转是什么?
控制反转(Inversion of Control,缩写为 IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做依赖注入(Dependency Injection,简称 DI),还有一种方式叫“依赖查找”(Dependency Lookup)。
通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。
什么是中间件(Middleware)?
中间件是组装到应用程序管道中以处理请求和响应的软件。 每个组件:
选择是否将请求传递给管道中的下一个组件。
可以在调用管道中的下一个组件之前和之后执行工作。
请求委托(Request delegates)用于构建请求管道,处理每个 HTTP 请求。
请求委托使用 Run,Map 和 Use 扩展方法进行配置。单独的请求委托可以以内联匿名方法(称为内联中间件)指定,或者可以在可重用的类中定义它。这些可重用的类和内联匿名方法是中间件或中间件组件。请求流程中的每个中间件组件都负责调用流水线中的下一个组件,如果适当,则负责链接短路。