在 .net Core 3.1 中用 Scrutor 装饰 Base Controller
Decorate BaseController with Scrutor in .netCore 3.1
我在 .net core 3.1 中有一个带有 angular 前端的应用程序。我想将装饰器用于基本控制器,以便在整个应用程序中记录 CUD 操作。我在项目中使用了 Scrutor nuget 包。
基地控制器如下
using System.Collections.Generic;
using System.Threading.Tasks;
using AutoMapper;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Xenagos.Data;
using Xenagos.Data.EFCore;
using Xenagos.ViewModels;
namespace Xenagos.Controllers
{
[Route("api/[controller]")]
[ApiController]
public abstract class BaseController<TEntity, TViewEntity, TRepository> : ControllerBase, IBaseController<TEntity, TViewEntity>
where TEntity : class
where TViewEntity : class, IViewEntity
where TRepository : IRepository<TEntity>
{
private readonly IRepository<TEntity> repository;
private readonly IMapper mapper;
public BaseController(TRepository repository, IMapper mapper)
{
this.repository = repository;
this.mapper = mapper;
}
// GET: api/[controller]
[HttpGet]
public virtual async Task<ActionResult<ComplexData<TViewEntity>>> Get()
{
var results = await repository.GetAll();
List<TViewEntity> resultsView =
this.mapper.Map<List<TEntity>, List<TViewEntity>>(results);
return Ok(new ComplexData<TViewEntity>(resultsView));
}
// GET: api/[controller]/5
[HttpGet("{id}")]
public async Task<ActionResult<TEntity>> Get(int id)
{
var entity = await repository.Get(id);
if (entity == null)
{
return NotFound();
}
return entity;
}
// PUT: api/[controller]/5
[HttpPut("{id}")]
public virtual async Task<IActionResult> Put(string id, TViewEntity entity)
{
if (!id.Equals(entity.Id))
{
return BadRequest();
}
await repository.Update(this.mapper.Map<TEntity>(entity));
return NoContent();
}
// POST: api/[controller]
[HttpPost]
public virtual async Task<ActionResult<TEntity>> Post(TViewEntity entity)
{
await repository.Add(this.mapper.Map<TEntity>(entity));
return CreatedAtAction("Get", new { id = entity.Id }, entity);
}
// DELETE: api/[controller]/5
[HttpDelete("{id}")]
public async Task<ActionResult<TViewEntity>> Delete(int id)
{
var entity = await repository.Delete(id);
if (entity == null)
{
return NotFound();
}
return this.mapper.Map<TViewEntity>(entity);
}
}
}
我做的装饰器如下
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Xenagos.Controllers;
using Xenagos.ViewModels;
namespace Xenagos.Data
{
public class LoggingDecorator<T, TViewEntity, TRepository> : IBaseController<T, TViewEntity>
where T : class
where TViewEntity : class, IViewEntity
where TRepository : IRepository<T>
{
private IBaseController<T, TViewEntity> _baseController;
private readonly ILogger<LoggingDecorator<T, TViewEntity, TRepository>> _logger;
public LoggingDecorator(IBaseController<T, TViewEntity> baseController, ILogger<LoggingDecorator<T, TViewEntity, TRepository>> logger)
{
_baseController = baseController;
_logger = logger;
}
Task<ActionResult<TViewEntity>> IBaseController<T, TViewEntity>.Delete(int id)
{
_logger.LogWarning($"Deleting record from ... with ID:{id}");
Task<ActionResult<TViewEntity>> result = _baseController.Delete(id);
return result;
}
public Task<ActionResult<ComplexData<TViewEntity>>> Get()
{
return _baseController.Get();
}
Task<ActionResult<T>> IBaseController<T, TViewEntity>.Get(int id)
{
return _baseController.Get(id);
}
public Task<ActionResult<T>> Post(TViewEntity entity)
{
_logger.LogWarning($"Adding new record from ... with object data :{JsonConvert.SerializeObject(entity)}");
return _baseController.Post(entity);
}
public Task<IActionResult> Put(string id, TViewEntity entity)
{
_logger.LogWarning($"updating record from ... with object data :{JsonConvert.SerializeObject(entity)}");
Task<IActionResult> result = _baseController.Put(id, entity);
return result;
}
}
}
在启动class中public void ConfigureServices(IServiceCollection)
我使用下面几行
services.AddScoped<IBaseController<Models.Property, PropertyViewModel>, BaseController<Models.Property, PropertyViewModel, PropertyRepository>>();
services.Decorate<IBaseController<Models.Property, PropertyViewModel>, LoggingDecorator<Models.Property, PropertyViewModel, PropertyRepository>>();
我已经从基本控制器中提取了一个接口,在所有之前的操作之上。
当应用程序运行时,它不会 call/pass-through 装饰器。我在这里缺少什么?
我以前没有在 .net 核心和依赖注入中使用过装饰器模式。所有添加的代码都只在后端,我根本没有改变前端。
提前致谢。
使用 ActionFilter
记录 enter/exit 控制器操作:
public class LoggingActionFilter : IActionFilter
{
ILogger _logger;
public LoggingActionFilter(ILoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger<LoggingActionFilter>();
}
public void OnActionExecuting(ActionExecutingContext context)
{
// do something before the action executes
_logger.LogInformation($"Action '{context.ActionDescriptor.DisplayName}' executing");
}
public void OnActionExecuted(ActionExecutedContext context)
{
// do something after the action executes
_logger.LogInformation($"Action '{context.ActionDescriptor.DisplayName}' executed");
}
}
启动
services.AddMvc()
.AddMvcOptions(options =>
{
options.Filters.Add<LoggingActionFilter>();
});
您可能还想为异步操作实施 IAsyncActionFilter
。
要了解有关操作过滤器的更多信息,请查看 here。
您还可以添加异常过滤器来记录所有异常。
我在 .net core 3.1 中有一个带有 angular 前端的应用程序。我想将装饰器用于基本控制器,以便在整个应用程序中记录 CUD 操作。我在项目中使用了 Scrutor nuget 包。
基地控制器如下
using System.Collections.Generic;
using System.Threading.Tasks;
using AutoMapper;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Xenagos.Data;
using Xenagos.Data.EFCore;
using Xenagos.ViewModels;
namespace Xenagos.Controllers
{
[Route("api/[controller]")]
[ApiController]
public abstract class BaseController<TEntity, TViewEntity, TRepository> : ControllerBase, IBaseController<TEntity, TViewEntity>
where TEntity : class
where TViewEntity : class, IViewEntity
where TRepository : IRepository<TEntity>
{
private readonly IRepository<TEntity> repository;
private readonly IMapper mapper;
public BaseController(TRepository repository, IMapper mapper)
{
this.repository = repository;
this.mapper = mapper;
}
// GET: api/[controller]
[HttpGet]
public virtual async Task<ActionResult<ComplexData<TViewEntity>>> Get()
{
var results = await repository.GetAll();
List<TViewEntity> resultsView =
this.mapper.Map<List<TEntity>, List<TViewEntity>>(results);
return Ok(new ComplexData<TViewEntity>(resultsView));
}
// GET: api/[controller]/5
[HttpGet("{id}")]
public async Task<ActionResult<TEntity>> Get(int id)
{
var entity = await repository.Get(id);
if (entity == null)
{
return NotFound();
}
return entity;
}
// PUT: api/[controller]/5
[HttpPut("{id}")]
public virtual async Task<IActionResult> Put(string id, TViewEntity entity)
{
if (!id.Equals(entity.Id))
{
return BadRequest();
}
await repository.Update(this.mapper.Map<TEntity>(entity));
return NoContent();
}
// POST: api/[controller]
[HttpPost]
public virtual async Task<ActionResult<TEntity>> Post(TViewEntity entity)
{
await repository.Add(this.mapper.Map<TEntity>(entity));
return CreatedAtAction("Get", new { id = entity.Id }, entity);
}
// DELETE: api/[controller]/5
[HttpDelete("{id}")]
public async Task<ActionResult<TViewEntity>> Delete(int id)
{
var entity = await repository.Delete(id);
if (entity == null)
{
return NotFound();
}
return this.mapper.Map<TViewEntity>(entity);
}
}
}
我做的装饰器如下
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Xenagos.Controllers;
using Xenagos.ViewModels;
namespace Xenagos.Data
{
public class LoggingDecorator<T, TViewEntity, TRepository> : IBaseController<T, TViewEntity>
where T : class
where TViewEntity : class, IViewEntity
where TRepository : IRepository<T>
{
private IBaseController<T, TViewEntity> _baseController;
private readonly ILogger<LoggingDecorator<T, TViewEntity, TRepository>> _logger;
public LoggingDecorator(IBaseController<T, TViewEntity> baseController, ILogger<LoggingDecorator<T, TViewEntity, TRepository>> logger)
{
_baseController = baseController;
_logger = logger;
}
Task<ActionResult<TViewEntity>> IBaseController<T, TViewEntity>.Delete(int id)
{
_logger.LogWarning($"Deleting record from ... with ID:{id}");
Task<ActionResult<TViewEntity>> result = _baseController.Delete(id);
return result;
}
public Task<ActionResult<ComplexData<TViewEntity>>> Get()
{
return _baseController.Get();
}
Task<ActionResult<T>> IBaseController<T, TViewEntity>.Get(int id)
{
return _baseController.Get(id);
}
public Task<ActionResult<T>> Post(TViewEntity entity)
{
_logger.LogWarning($"Adding new record from ... with object data :{JsonConvert.SerializeObject(entity)}");
return _baseController.Post(entity);
}
public Task<IActionResult> Put(string id, TViewEntity entity)
{
_logger.LogWarning($"updating record from ... with object data :{JsonConvert.SerializeObject(entity)}");
Task<IActionResult> result = _baseController.Put(id, entity);
return result;
}
}
}
在启动class中public void ConfigureServices(IServiceCollection)
我使用下面几行
services.AddScoped<IBaseController<Models.Property, PropertyViewModel>, BaseController<Models.Property, PropertyViewModel, PropertyRepository>>();
services.Decorate<IBaseController<Models.Property, PropertyViewModel>, LoggingDecorator<Models.Property, PropertyViewModel, PropertyRepository>>();
我已经从基本控制器中提取了一个接口,在所有之前的操作之上。 当应用程序运行时,它不会 call/pass-through 装饰器。我在这里缺少什么? 我以前没有在 .net 核心和依赖注入中使用过装饰器模式。所有添加的代码都只在后端,我根本没有改变前端。
提前致谢。
使用 ActionFilter
记录 enter/exit 控制器操作:
public class LoggingActionFilter : IActionFilter
{
ILogger _logger;
public LoggingActionFilter(ILoggerFactory loggerFactory)
{
_logger = loggerFactory.CreateLogger<LoggingActionFilter>();
}
public void OnActionExecuting(ActionExecutingContext context)
{
// do something before the action executes
_logger.LogInformation($"Action '{context.ActionDescriptor.DisplayName}' executing");
}
public void OnActionExecuted(ActionExecutedContext context)
{
// do something after the action executes
_logger.LogInformation($"Action '{context.ActionDescriptor.DisplayName}' executed");
}
}
启动
services.AddMvc()
.AddMvcOptions(options =>
{
options.Filters.Add<LoggingActionFilter>();
});
您可能还想为异步操作实施 IAsyncActionFilter
。
要了解有关操作过滤器的更多信息,请查看 here。
您还可以添加异常过滤器来记录所有异常。