gpt4 book ai didi

c# - 消除工厂中的 IoC 容器耦合

转载 作者:太空宇宙 更新时间:2023-11-03 10:50:30 26 4
gpt4 key购买 nike

我有多个多语言“网站”在单个网络应用程序下运行。每个“语言环境”都有自己的 Solr 核心(在所有语言环境中具有相同的字段)。我正在使用 SolrNet 执行我的搜索查询。

为了根据每个请求切换内核,我正在注册一个 ISolrOperations<SearchResult>命名实例在我的每个语言环境的 Autofac 容器中(对于那些不熟悉 SolrNet 的人,这实际上是我进入库以进行查询的入口点)。

然后我有一个 ISearchService界面,带混凝土SolrSearchService实现,其构造函数签名如下所示:

public SolrSearchService(ISolrOperations<SearchResult> solr)

为了根据每个请求动态切换核心,我的 Controller 采用(注入(inject)的)ISearchServiceFactory而不是简单的 ISearchService .我的SolrSearchServiceFactory看起来像这样:

public class SolrSearchServiceFactory : ISearchServiceFactory
{
private readonly IComponentContext _ctx;

public SolrSearchServiceFactory(IComponentContext ctx)
{
_ctx = ctx;
}

public ISearchService Create(string id)
{
var result = _ctx.ResolveNamed<ISolrOperations<SearchResult>>(id);
return new SolrSearchService(result);
}
}

id只是语言环境标识符。这是我为将 Autofac 与我的服务/ Controller 分离但保持按请求切换内核的能力(基于 Controller 中执行的逻辑)所做的最好的事情。

然而,我对此仍然不是很满意,因为工厂本身仍然与 Autofac 耦合。有没有办法解决这个问题(从 SolrNet 或 Autofac 的角度来看)?

我看过使用 Autofac 的工厂代表,但似乎没有办法在这种情况下应用它们。

最佳答案

您可以使用键控/命名服务和 IIndex 来执行此操作,autofac 页面上有一个很好的条目 here .

这是一个简单的示例:

    public class Factory
{
private readonly IIndex<string, ISearchService> _index;

public Factory(IIndex<string, ISearchService> index)
{
_index = index;
}

public ISearchService Resolve(string id)
{
return _index[id];
}
}

// Registrations
var builder = new ContainerBuilder();
builder.Register<ASearchService>(c => new ASearchService()).Keyed<ISearchService>("A");
builder.Register<BSearchService>(c => new BSearchService()).Keyed<ISearchService>("B");
builder.Register<Factory>(c => new Factory(c.Resolve<IIndex<string, ISearchService>>()));
// as per autofac's page linked above, autofac automatically implements IIndex types

// Usage

var aSearchService = fact.Resolve("A");

编辑:我认为我们可以做得更好,所以这里有几个扩展方法来避免创建显式工厂类:

    public delegate TReturn AutoFactoryDelegate<TParam, TReturn>(TParam param);

public class AutoFactory<TParam, TReturn>
{
private readonly IIndex<TParam, TReturn> _index;

public AutoFactory(IIndex<TParam, TReturn> index)
{
_index = index;
}

public TReturn Resolve(TParam param)
{
return _index[param];
}
}

public delegate TReturn AutoFactoryDelegate<TParam, TReturn>(TParam param);

public static class AutofacExtensions
{
public static void RegisterAutoFactoryDelegate<TParam, TReturn>(this ContainerBuilder builder)
{
builder.Register(c => new AutoFactory<TParam, TReturn>(c.Resolve<IIndex<TParam, TReturn>>()));

builder.Register<AutoFactoryDelegate<TParam, TReturn>>(c =>
{
var fact = c.Resolve<AutoFactory<TParam, TReturn>>();
return fact.Resolve;
});
}
}

// Registration
var builder = new ContainerBuilder();
builder.Register<ASearchService>(c => new ASearchService()).Keyed<ISearchService>("A");
builder.Register<BSearchService>(c => new BSearchService()).Keyed<ISearchService>("B");
builder.RegisterAutoFactoryDelegate<string, ISearchService>();

// Usage
// fact is an AutoFactoryDelegate<string, ISearchService>
var aSearchService = fact("A");

编辑 2:再次查看后,我们不需要工厂类,因为 IIndex 实际上已经是工厂了。这导致实现方面的相当大的简化:

public static void RegisterAutoFactoryDelegate<TParam, TReturn>(this ContainerBuilder builder)
{
builder.Register(c =>
{
var iindex = c.Resolve<IIndex<TParam, TReturn>>();
return (Func<TParam, TReturn>) (id => iindex[id]);
});
}

// Registration
var builder = new ContainerBuilder();
builder.Register<ASearchService>(c => new ASearchService()).Keyed<ISearchService>("A");
builder.Register<BSearchService>(c => new BSearchService()).Keyed<ISearchService>("B");
builder.RegisterAutoFactoryDelegate<string, ISearchService>();

// Usage
// fact is an Func<string, ISearchService>
var aSearchService = fact("A");

关于c# - 消除工厂中的 IoC 容器耦合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21588426/

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