gpt4 book ai didi

c# - 通过上下文解决依赖关系 - 深入解析树

转载 作者:行者123 更新时间:2023-11-30 16:40:08 26 4
gpt4 key购买 nike

我们有两个应用程序共享一些具有依赖性的公共(public)类。这些依赖关系对于两者都是相同的,或者是特定于应用程序的。

现在为两个应用配置 IoC 很容易 - 使用 ImplementationA 作为一个应用的 IDependency,使用 ImplementationB 作为另一个应用的 IDependency。

但是 - 有第三个应用程序,有时在解析接口(interface)时需要使用应用程序 A 的依赖项,有时需要使用应用程序 B 的依赖项。换句话说,我需要这样的东西:

Resolve<ISomething>( when you come accross IDependecy (anywhere in the 'resolve tree') use ImplementationA)

Resolve<ISomething>( when you come accross IDependecy (anywhere in the 'resolve tree') use ImplementationB)

所以核心问题是:如何将上下文传递给从 Resolve 调用中选择实现的任何逻辑?

具体例子:.NET Core MVC App - 从请求中解析枚举值。现在我需要调用一些 IManagerFactory,将此枚举作为参数传递,并从应用程序 A 或 B 获取具有所有依赖项的管理器的实现。(再次强调,深入不仅仅是管理器本身的依赖项)
从请求中获取上下文非常耗时,所以我只想做一次。这已经在方法开始时完成了。像这样

public async Task<Response> ProcessRequest([FromBody] Request request)
{
var context = _someService.GetContext(request);
var appType = ParseAppTypeFromContext(context);
...
var manager= _managerFactory.Resolve(appType);
manager.DoSomething();
manager.DoSomethingElse();
}

可能的解决方案:

  1. 我可以注册 ISomethingA,使用注册委托(delegate)并让它通过 ResolvedParameter(Autofac 功能)解析正确的依赖关系 - 然后只解析 ISomethingA。

但我必须为依赖于 IDependecy 的每个类和依赖于该类的每个类等等做这件事——按我的方式做。

  1. 使用工厂。
    但是您仍然必须以某种方式告诉它您想要哪种实现。所以我必须从上到下传递该信息 - 这似乎有点.. 错误,因为这些是不应该知道有一些应用程序 A 或 B 的常见类。

所以..我迷路了。我不确定这是否适用于 IoC 或更好的设计。请指教。
(我真的不在乎我使用哪个 IoC 容器——只要它是好的和维护的)

最佳答案

在我看来,使用工厂确实是错误的方法。工厂使 IDependency 的使用者变得复杂,引入此工厂抽象可能会导致整个应用程序发生彻底的变化。

相反,我认为最合适的解决方案是应用代理模式。此代理将是 IDependency 的实现,它将包装两个 IDependency 实现,并将根据您指定的条件将任何传入调用分派(dispatch)到正确的实现。

例如:

public class DependencyDispatcher : IDependency
{
private ImplA a;
private ImplB b;

public DependencyDispatcher(ImplA a, ImplB b) {
this.a = a;
this.b = b;
}

private IDependency Dependency => someCondition ? this.a : this.b;

// Implement IDependency methods to forward the call to Dependency
void IDependency.DoSomething() => this.Dependency.DoSomething();
}

您可以将此代理配置为 Composition RootIDependency 的默认实现你的第三次申请。

您的更新让事情变得更加清晰。您在请求中设置了一些运行时值,您需要根据该值做出决定。

这里有一些解决方案。首先,尝试将此决定从请求正文 移到请求 header 中。这样,您的调度员可以执行以下操作:

private IDependency Dependency => 
HttpContext.Current.Headers["MyHeader"] == "something" ? this.a : this.b;

如果这不是一个选项,并且信息属于在请求正文中,您可以让您的调度员根据其输入做出决定。例如:

public class DependencyDispatcher : IDependency
{
...

private IDependency GetDependency(string appType) =>
appType == "a" ? this.a : this.b;

void IDependency.DoSomething(DoSomethingData data) =>
this.GetDependency(data.AppType).DoSomething(data);
}

这显然只有在将 AppType 值(或可以转换为它的值)提供给 IDependency 的方法时才有可能。只有在那种情况下,有足够的可用信息才能做出此决定。

如果那不是一个选项,另一个选项是定义一个允许在对象图中设置运行时值的抽象,它为调度程序提供该请求的信息。例如:

public interface IApplicationContext
{
AppType ApplicationType { get; set; }
}

您的 Controller 可以注入(inject)此 IApplicationContext 并设置 AppType 属性:

public async Task<Response> ProcessRequest([FromBody] Request request)
{
var context = _someService.GetContext(request);
this.applicationContext.ApplicationType = ParseAppTypeFromContext(context);
this.dependency.DoSomethingElse();
}

或者,您可以添加一些中间件,在调用 Controller 的 Action 方法之前设置 AppType

您也可以让 Proxy 实现 IApplicationContext:

public class DependencyDispatcher : IDependency, IApplicationContext
{
...
public AppType ApplicationType { get; set; }

private IDependency Dependency => ApplicationType == AppType.A ? this.a : this.b;

// Implement IDependency methods to forward the call to Dependency
void IDependency.DoSomething() => this.Dependency.DoSomething();
}

关于c# - 通过上下文解决依赖关系 - 深入解析树,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51855355/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com