接口接口<T>:T

Gel*_*pon 5 .net c# generics inheritance interface

假设我有这样的类和接口结构:

interface IService {}
interface IEmailService : IService
{
    Task SendAsync(IMessage message);
}

class EmailService : IEmailService
{
    async Task SendAsync(IMessage message)
    {
        await ...
    }
}

interface ICircuitBreaker<TService> : IService where TService : IService
{
    TService Service { get; set; }
    Task<IResult> PerformAsync(Func<Task<Iresult>> func);
}

class EmailServiceCircuitBreaker : ICircuitBreaker<IEmailService>
{
    IEmailService Service { get; set; }

    public EmailServiceCircuitBreaker(IEmailService service)
    {
        Service = service;
    }

    public async Task<IResult> PerformAsync(Func<Task<Iresult>> func)
    {
        try
        {
            func();
        }
        catch(Exception e){//Handle failure}
    }
}
Run Code Online (Sandbox Code Playgroud)

所以现在我想EmailServiceCircuitBreaker改为:

class EmailServiceCircuitBreaker : ICircuitBreaker<IEmailService>, IEmailService
Run Code Online (Sandbox Code Playgroud)

所以我可以包装每个方法,IEmailService并且Send(...)看起来像:

async Task<IResult> IEmailService.SendAsync(IMessage m)
    => await PerformAsync(async () => await Service.SendAsync(m));
Run Code Online (Sandbox Code Playgroud)

在控制器中我可以使用它,IEmailService即使这是ICircuitBreaker<IEmailService>不知道的。

但是,如果我的任何同事将实施ICircuitBreaker<T>我想强制他的班级也实施T

Vib*_*nRC 3

当您不想有新的语言约束时,您可以在编译时抛出自定义错误

您可以如下创建代码分析,使用DiagnosticAnalyzer

https://johnkoerner.com/csharp/creating-your-first-code-analyzer/

使用DiagnosticAnalyzer,您可以搜索模式并抛出异常

 context.RegisterSymbolAction(AnalyzeSymbol, SymbolKind.NamedType);

        private static void AnalyzeSymbol(SyntaxNodeAnalysisContext context)
        {
            var node = (ObjectCreationExpressionSyntax)context.Node;

            if (node != null && node.Type != null && node.Type is IdentifierNameSyntax)
            {
                var type = (IdentifierNameSyntax)node.Type;

                var symbol = (INamedTypeSymbol)context.SemanticModel.GetSymbolInfo(type).Symbol;
                var isIService = IsInheritedFromIService(symbol);

                if (isIService )
                {
                   ... //Check you logic
                    context.ReportDiagnostic(diagnostic);
                }
            }
        }

    private static bool IsInheritedFromIService(ITypeSymbol symbol)
    {
        bool isIService = false;
        var lastParent = symbol;

        if (lastParent != null)
        {
            while (lastParent.BaseType != null)
            {
                if (lastParent.BaseType.Name == "IService")
                {
                    isIService = true;
                    lastParent = lastParent.BaseType;
                    break;
                }
                else
                {
                    lastParent = lastParent.BaseType;
                }
            }
        }

        return isIService ;
    }
Run Code Online (Sandbox Code Playgroud)