C# 接口<;T>;:T

C# 接口<;T>;:T,c#,.net,generics,inheritance,interface,C#,.net,Generics,Inheritance,Interface,假设我有这样的类和接口结构: interface IService {} interface IEmailService : IService { Task SendAsync(IMessage message); } class EmailService : IEmailService { async Task SendAsync(IMessage message) { await ... } } interface ICircuitBrea

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

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}
    }
}
因此,我可以包装
IEmailService
中的每个方法,
Send(…)
将如下所示:

async Task<IResult> IEmailService.SendAsync(IMessage m)
    => await PerformAsync(async () => await Service.SendAsync(m));
异步任务IEmailService.SendAsync(IMessage m) =>wait-PerformAsync(async()=>wait-Service.sendaync(m)); 在控制器中,我可以将其用作
IEmailService
,即使这是
icirciitbreaker
,我也不知道


但是,如果我的任何同事将实现
ICircitBreaker
,我想强制他的类在不需要新的语言约束时也实现
T
,那么在编译时可以抛出自定义错误

您可以使用DiagnosticAnalyzer

使用
DiagnosticanAnalyzer
,您可以搜索模式并引发异常

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

描述似乎有点倒退,但您是否试图描述一个类似于Eric Lippert中描述的场景?问题到底是什么?部件
接口接口:IService,其中IService:T
在语法上不正确;类型约束必须在类型参数上。据我所知,C#不支持这种约束,如果您不希望所有团队成员都遵守严格的规则,您可以使用Roslyn的功能Compiler@Codor是的,我知道incorrect@VibeeshanRC你能提供一些关于这个主题的链接吗?
 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 ;
    }