如何检查所有现有和未来的”ICheck”实现,以获取正确的内容类型。

huangapple go评论59阅读模式
英文:

how to check logic from all existing and future implementation of "ICheck" to get the right content type

问题

我有一个接口,我正在返回检查结果,这个接口目前有两个实现,但将来会不断添加。

public interface ICheck
{
    Task<CheckReturn> GetCheckReturn(string fileName);
}

public class ATypeCheck : ICheck
{
    public async Task<CheckReturn> GetCheckReturn(string fileName)
    {
        //检查 A 类型的逻辑
        //返回带有正确内容类型的 CheckReturn
        return await Task.FromResult<CheckReturn>(new CheckReturn { ContentType = "Type A" });
    }
}

public class BTypeCheck : ICheck
{
    public async Task<CheckReturn> GetCheckReturn(string fileName)
    {
        //检查 B 类型的逻辑
        //返回带有正确内容类型的 CheckReturn
        return await Task.FromResult<CheckReturn>(new CheckReturn { ContentType = "Type B" });
    }

    // 未来的 CTypeCheck
    // 未来的 DTypeCheck

使用下面的代码,我只能进行一次检查验证,但我需要检查所有 ICheck 的实现?

static async Task Main(string[] args)
{
    ATypeCheck check = new ATypeCheck();

    var result = await check.GetCheckReturn("XYZ");
}

哪种设计模式在这里有帮助,以及如何?

英文:

I have a interface where I am returning result for a check and this interface has currently 2 implantations but in future it will keeps added.

public interface ICheck
{
    Task&lt;CheckReturn&gt; GetCheckReturn(string fileName);
}

public class ATypeCheck : ICheck
{
    public async Task&lt;CheckReturn&gt; GetCheckReturn(string fileName)
    {
        //logic to check A Type
        //return CheckReturn with right content type
        return await Task.FromResult&lt;CheckReturn&gt;(new CheckReturn { ContentType = &quot;Type A&quot; });
    }
}

public class BTypeCheck : ICheck
{
    public async Task&lt;CheckReturn&gt; GetCheckReturn(string fileName)
    {
        //logic to check A Type
        //return CheckReturn with right content type
        return await Task.FromResult&lt;CheckReturn&gt;(new CheckReturn { ContentType = &quot;Type B&quot; });
    }
}

> // Future CTypeCheck
> // Future DTypeCheck

With below code I am able to do only one check validation, but I need to check all the implementation of ICheck?

static async Task Main(string[] args)
    {
        ATypeCheck check = new ATypeCheck();

        var result = await check.GetCheckReturn(&quot;XYZ&quot;);
    }

Which design pattern help here & how?

答案1

得分: 1

以下是翻译好的部分:

Part 1: Code against interfaces

static async Task Main(string[] args)
{
    ICheck checks = new List<ICheck>{ new ATypeCheck(), new BTypeCheck() };
    var results = new List<CheckResult>();
    foreach( var check in checks ) results.Add(await check.GetCheckReturn("XYZ"));

    // TODO 处理结果 
}

Part 2: Dependency Injection
在生产代码中,您可能希望在启动时检测接口的所有实现,并将这些接口实现的列表注入到客户端中。

您可以使用反射来实现这一点

关于这个问题已经有相关的问题,因此我认为这一部分是重复的。您可以参考,例如,这个 问题。

我建议通过 DI 来完成这个操作,而不是在运行时执行,因为反射可能会很慢,您希望在启动时完成它,然后就可以了。但您不一定要使用 DI

当然,您也可以像 Part 1 的示例一样构建实现列表。但这意味着您必须跟踪新的实现并将它们添加到其中(这是不好的,最终会导致“遗忘”实现)。

英文:

2 Parts to a solution:

Part 1: Code against interfaces

static async Task Main(string[] args)
{
    ICheck checks = new List&lt;ICheck&gt;{ new ATypeCheck(), new BTypeCheck() };
    var results = new List&lt;CheckResult&gt;();
    foreach( var check in checks ) results.Add(await check.GetCheckReturn(&quot;XYZ&quot;));

    // TODO handle results 
}

Part 2: Dependency Injection

In production code, you probably will want to detect all implementations of the interface at startup and inject your clients with that list of interface-implementations.

You can do that using reflection.

There are questions regarding this already, so I would consider this part a duplicate. You can refer to for example this question.

The reason I recommend doing this via DI and not just at runtime is that reflection might be slow and you would want that done once at startup and that's it. But you are not locked in to DI.

You could of course as well just construct the list of implementations like in the example of Part 1. But that would mean you'd have to keep track of new implementations and add them there (which is bad and will lead to "forgotten" impls sooner or later).

答案2

得分: 1

如果您正在使用 DI,您可以注册各种实现,然后将它们注入为IEnumerable&lt;YourInterface&gt;

例如:

public class SomeConsumer() {
  private readonly IEnumerable&lt;IYourInterface&gt; _allServices;

  public SomeConsumer(IEnumerable&lt;IYourInterface&gt; allServices) {
    _allServices = allServices;
    // ...
  }
  
  // 在代码中使用 _allServices 来获取所有的实现
}

要注册各种实现,请使用标准的AddScoped、AddTransient等方法。

// Program.cs
// ...
builder.Services.AddScoped&lt;IYourInterface, Implementation1&gt;();
builder.Services.AddScoped&lt;IYourInterface, Implementation2&gt;();
//...
英文:

If you're using DI you could register various implementations and then inject them as IEnumerable&lt;YourInterface&gt;

eg.

public class SomeConsumer() {
  private readonly IEnumerable&lt;IYourInterface&gt; _allServices;

  public SomeConsumer(IEnumerable&lt;IYourInterface&gt; allServices) {
    _allServices = allServices;
    // ...
  }
  
  // use _allServices in code to get all implementations
}

To register various implementations use standard AddScoped, AddTransient etc. methods.

// Program.cs
// ...
builder.Services.AddScoped&lt;IYourInterface, Implementation1&gt;();
builder.Services.AddScoped&lt;IYourInterface, Implementation2&gt;();
//...

huangapple
  • 本文由 发表于 2023年2月16日 15:26:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/75469020.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定