接口 Interface<T> 实现了泛型 T。

5

假设我有以下类和接口的结构:

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}
    }
}

现在我想将EmailServiceCircuitBreaker更改为:

class EmailServiceCircuitBreaker : ICircuitBreaker<IEmailService>, IEmailService

这样我就可以包装IEmailService中的每个方法,Send(...)将会变成:

async Task<IResult> IEmailService.SendAsync(IMessage m)
    => await PerformAsync(async () => await Service.SendAsync(m));

在控制器中,即使这是 ICircuitBreaker<IEmailService>,我仍然可以将其用作 IEmailService,而无需知道它的具体内容。

但是,如果我的任何同事要实现 ICircuitBreaker<T>,我希望强制他的类也实现 T


3
描述似乎有些反向,但您是在描述类似于Eric Lippert的《越来越好奇》(Curiouser and Curiouser)中所描述的情景吗? - Damien_The_Unbeliever
4
这个问题的确切意思是什么?interface IInterface<T> : IService where IService : T这部分语法不正确,类型约束必须放在类型参数上。 - Codor
据我所知,C#不支持这种类型的约束。如果您希望所有团队成员遵循严格的规则,可以使用Roslyn编译器的功能。 - VibeeshanRC
@Codor 是的,我知道那是不正确的。 - Geli Papon
@VibeeshanRC 是的,看起来不错,但也许有人会有其他解决方案。 - Geli Papon
显示剩余2条评论
1个回答

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 ;
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接