ASPNET 样板,扩展审计日志

问题描述

我正在尝试扩展 ASPNETBOILETPLATE 框架中的 AuditLog 实体,以便为其添加一些新属性。我尝试扩展 AuditLog 类 (ExtendedAuditInfo) 并实现 AuditStore 类 (ExtendedAuditStore) 的自定义版本。但是,我无法在构造函数中注入我的新 ExtendedAuditInfo 并收到两条关于 ConstructorSaveAsync 方法中的输入参数不匹配的错误消息。

Class ExtendedAuditInfo

public class ExtendedAuditInfo : AuditInfo
{
    // Some properties
}

ExtendedAuditStore

public class ExtendedAuditStore : AuditingStore
{
    public ExtendedAuditStore(IRepository<ExtendedAuditInfo,long> auditLogRepository)
        : base(auditLogRepository)
    {
    }

    public override Task SaveAsync(ExtendedAuditInfo auditInfo)
    {
        if (!string.IsNullOrEmpty(auditInfo.Parameters) && auditInfo.Parameters != "{}")
        {
            var parameters = JsonConvert.DeserializeObject<AuditParameterInput>(auditInfo.Parameters);
            if (parameters != null)
                auditInfo.CustomData = parameters.Input.Id.ToString();
        }

        return base.SaveAsync(auditInfo);
    }
}

错误是:

无法从 'Abp.Domain.Repositories.IRepository' 转换为 'Abp.Domain.Repositories.IRepository'

找不到合适的方法来覆盖

以上过程基于我发现 Here

解决方法

我根据How To Extend Existing Entities的官方文档找到了解决方案。

为了扩展 AuditLog 类,必须使用继承。因此,一个新类,假设 ExtendedAuditInfo 需要从 AuditLog 继承。

public class ExtendedAuditLog : AuditLog
    {
        public ExtendedAuditLog()
        {

        }

        public ExtendedAuditLog(AuditInfo auditInfo)
        {
            this.BrowserInfo = auditInfo.BrowserInfo;
            this.ClientIpAddress = auditInfo.ClientIpAddress;
            this.ClientName = auditInfo.ClientName;
            this.CustomData = auditInfo.CustomData;
            this.Exception = auditInfo.Exception?.Message.ToString() + "";
            this.ExecutionDuration = auditInfo.ExecutionDuration;
            this.ExecutionTime = auditInfo.ExecutionTime;
            this.ImpersonatorTenantId = auditInfo.ImpersonatorTenantId;
            this.ImpersonatorUserId = auditInfo.ImpersonatorUserId;
            this.MethodName = auditInfo.MethodName;
            this.Parameters = auditInfo.Parameters;
            this.ReturnValue = auditInfo.ReturnValue;
            this.ServiceName = auditInfo.ServiceName;
            this.TenantId = auditInfo.TenantId;
            this.UserId = auditInfo.UserId;
        }

        //new properties
    }

必须将此类添加到上下文中,显然,需要运行新的迁移才能添加新属性。

public class ProjectDbContext : AbpZeroDbContext<Tenant,Role,User,ProjectDbContext >
{
    /* Define a DbSet for each entity of the application */
    
    public SerafinaDbContext(DbContextOptions<SerafinaDbContext> options)
        : base(options)
    {
    }

    public virtual DbSet<County> Counties { get; set; }

    public virtual DbSet<Country> Countries { get; set; }

    public virtual DbSet<Currency> Currencies { get; set; }

    public virtual DbSet<OrganisationType> OrganisationTypes { get; set; }

    public virtual DbSet<ExtendedAuditLog> ExtendedAuditLogs { get; set; }
}

最后,在 ExtendedAuditStore 类中,IRepository<ExtendedAuditLog,long> _extendedAuditLogRepository 必须作为构造函数的第二个参数注入,并可用于插入扩展实体。

public class ExtendedAuditStore : AuditingStore
{
    IRepository<ExtendedAuditLog,long> _extendedAuditLogRepository;

    public ExtendedAuditStore(
        IRepository<AuditLog,long> auditLogRepository,IRepository<ExtendedAuditLog,long> extendedAuditLogRepository
        )
        : base(auditLogRepository)
    {
        _extendedAuditLogRepository = extendedAuditLogRepository;
    }

    public override async Task SaveAsync(AuditInfo auditInfo)
    {
        if (auditInfo.Exception != null)
            await base.SaveAsync(auditInfo);

        var auditLog = new ExtendedAuditLog(auditInfo);
        //new properties can be set here
        await _extendedAuditLogRepository.InsertAsync(auditLog);
    }
}

此外,可以创建 IAuditingStore 的新实现并将其注入到应用程序服务中,而不是从 AuditingStore 继承。

更新:

最后,您只需要替换 AuditingStore 类中的默认 StartUp

public IServiceProvider ConfigureServices(IServiceCollection services)
{
    services.AddTransient<IAuditingStore,ExtendedAuditStore>();
}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...