【问题标题】:interface Interface<T> : T接口接口<T>:T
【发布时间】:2017-08-11 13:51:43
【问题描述】:

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

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

所以我可以包装 IEmailServiceSend(...) 中的每个方法,如下所示:

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

在控制器中,我可以将其用作IEmailService,即使这是ICircuitBreaker&lt;IEmailService&gt;,但我并不知道。

但是,如果我的任何同事将实施ICircuitBreaker&lt;T&gt;,我想强制他的班级也实施T

【问题讨论】:

  • 描述似乎有点倒退,但您是否试图描述类似于 Eric Lippert 的Curiouser and Curiouser 中描述的场景?
  • 问题到底是什么? interface IInterface&lt;T&gt; : IService where IService : T 部分语法不正确;类型约束必须在类型参数上。
  • 据我所知 C# 不支持这种约束,如果你不希望你的所有团队成员都遵守严格的规则,你可以使用 Roslyn 编译器的功能
  • @Codor 是的,我知道这是不正确的
  • @VibeeshanRC 你能提供一些关于这个话题的链接吗?

标签: c# .net generics inheritance interface


【解决方案1】:

如果你不想有新的语言约束,那么你可以在编译时抛出自定义错误

您可以如下创建代码分析,使用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 ;
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-18
    • 1970-01-01
    • 1970-01-01
    • 2022-11-10
    • 2011-04-04
    相关资源
    最近更新 更多