Unity将两个接口注册为一个单例

更新时间:2024-05-05 下载TXT文档 下载Word文档

我如何在同一个实例中注册两个不同的接口...
目前我正在使用

        _container.RegisterType<EventService, EventService>(new ContainerControlledLifetimeManager());
        _container.RegisterInstance<IEventService>(_container.Resolve<EventService>());
        _container.RegisterInstance<IEventServiceInformation>(_container.Resolve<EventService>());

哪个可行,但看起来不太好..

所以,我想你明白了。 EventService实现了两个接口,如果我解析这些接口,我希望引用同一个对象。

克里斯

  • 好吧,如果这是要走的路,我就保留它。 只是想知道是否有一种更优雅的方法,但是它正在起作用,这就是重点。 到目前为止,我真的很喜欢Unity。
  • 看看Svens的答案...它有很多优点。 请查看@Chris Tavares对我的回答的评论,以获取更多详细信息。 检查一下,如果您喜欢,Id敦促您将其标记为其他人的答案。

[第二次编辑]

由于Unity处理注册方式的重大变化,更新的方法不再起作用。 [原始答案]是再次走的路。 (有关Unity中更改的更多详细信息,请参阅下面的注释中给出的链接。)

[编辑]

通过XML配置执行此操作的解决方案可在此处找到。 基于该答案,我将提出一种简化的仅代码方式,如下所示:

_container.RegisterType<IEventService, EventService>(new ContainerControlledLifetimeManager());
_container.RegisterType<IEventServiceInformation, EventService>(new ContainerControlledLifetimeManager());
bool singleton = ReferenceEquals(_container.Resolve<IEventService>(), _container.Resolve<IEventServiceInformation>());

这样,EventService类本身不会由容器发布。由于应将类视为实现细节,因此这是首选方法。

[原始回答]

答案迟了一点,但应该可以解决:

_container.RegisterType<EventService>(new ContainerControlledLifetimeManager());
_container.RegisterType<IEventService, EventService>();
_container.RegisterType<IEventServiceInformation, EventService>();

bool singleton = ReferenceEquals(_container.Resolve<IEventService>(), _container.Resolve<IEventServiceInformation>());
  • 有谁知道如何通过配置来做到这一点?
  • 我也想知道如何通过配置来做到这一点。
  • 有趣的是,(至少在这里)似乎在将其中一个设置为命名注册时不起作用...
  • 是的,使用命名注册似乎无效,不幸的是,这正是我所需要的。
  • 我遵循了您为Unity 5.10编辑的答案,结果证明不是单例。因此,除非我做错了什么,否则这个答案可能会过时。
  • 同样的问题,这里没有注册为单例。我们正在使用版本5.8.13。
  • @ grek40实际上,根据github.com/unitycontainer/unity/wiki,这是Unity 5.2.1中的重大更改。从该版本开始,[原始答案]再次成为您的朋友;)
  • @SvenKnzler您可以添加第二个编辑来阐明此更改吗?现在,这有点误导,人们会像我一开始那样继续做错事。
  • @ JacobsDataSolutions,@ Reddog,对于需要名称的人,您可以将其用于您的其中一个命名注册,虽然有些古怪,但可以使用:_container.RegisterInstance("es1", container.Resolve());

编辑 [短码网_DuanMa.NET]

在评论中获得一些反馈后,我认为Sven的答案是一个更好的答案。感谢克里斯·塔瓦雷斯(Chris Tavares)指出技术优点。

那几乎是唯一的方法。

您可以对其进行一些修改(我讨厌每个通用参数都具有相同类型的RegisterType):

EventService es = _container.Resolve<EventService>();
_container.RegisterInstance<IEventService>(es);
_container.RegisterInstance<IEventServiceInformation>(es);

如果您的IoC子级中的一个或多个要请求具体的EventService类型(希望不是),您将再添加一个类型为RegisterInstanceRegisterInstance。希望您不需要,所有依赖对象都要求一个IEventService,而不是一个EventService

希望这可以帮助,
安德森

  • 依赖注入的优良作法是将布线时间与解决时间尽可能地分开。该解决方案的缺点是它要求您将要解决的呼叫与注册的呼叫混合使用
  • @Nigel Thorne:通常是这样,但是在这种情况下,OP具有他/她需要注册的服务,该服务具有很多依赖性。我建议Unity创建此对象,以便自动解决这些依赖关系,以便该实例可用于两个Register调用(他/她需要为两个接口返回的实例完全相同)。通常,这是不希望的,但是在这种情况下,这实际上是唯一的方法(除了手动实例化对象之外)。
  • 这实际上不是要走的路-请使用下面的Sven Kunzlers答案。
  • @克里斯·塔瓦雷斯我同意我更喜欢他。但是,很难说我的答案是错误的。
  • @Anderson-很好,这种方法确实有效,但是它有两个不利的副作用。首先,两次RegisterInstance调用导致两个生命周期管理器,这意味着Dispose将在对象上被调用两次。取决于类型,这可能是问题,也可能不是问题。另一个问题是:如果EventService本身具有依赖项,该怎么办?在这种情况下,您必须确定所有EventServices依赖项都已在容器中注册后才能进行Resolve调用。使用RegisterType方法,您可以随时注册它。
  • @克里斯·塔瓦雷斯(Chris Tavares):我没有意识到第一个问题,至于第二个问题,这就是我为什么要对我使用斯文斯方法的原因……我遇到了这个问题,你是正确的。
  • @克里斯·塔瓦雷斯(Chris Tavares):我已经更新了答案,将斯文斯称为首选答案。感谢您抽出宝贵时间对此发表评论。阅读此书将使很多人受益。

对于这种简单的事情,适配器方法似乎体积很大,因此我进一步研究了一下。要解决命名实例的问题,您需要注册类型,并注册接口的工厂。

 InjectionFactory factory = new InjectionFactory(x => x.Resolve<SimulationService>());
 this.Container.RegisterType<SimulationService>(new ContainerControlledLifetimeManager());
 this.Container.RegisterType<IContentProvider>("SimulationContentProvider", factory);
 this.Container.RegisterType<ISimulationService>(factory);

这样,您无需创建具体类的实例(在注册时),在我的情况下由于缺少依赖项而无法创建实例。

  • 这似乎是正确的答案。我不喜欢其他解决方案依赖于注册期间解析类的具体实例的想法,这样可以避免这种情况。我希望Unity可以针对这些"更复杂"的使用提供更好的文档。

使用多个接口进行单例的正确方法如下:

_container.RegisterType<EventService>(TypeLifetime.Singleton); <- This could be an instance
_container.RegisterType<IEventService, EventService>();
_container.RegisterType<IOtherEventService, EventService>();

您需要分别注册一个单例及其所有映射。 Unity v6将有一种注册方法可以一次完成所有操作。

一种也适用于命名实例的解决方案是使用适配器模式为包装围绕单例实例的接口创建一次性适配器。然后,如果使用ResolveAll解析实例,则将始终将其定向到单例实例。当拥有大量实现通用接口(如IStartable或诸如此类)的服务时,这会有所帮助。

public class EventServiceAdapter< T > : IEventService where T : IEventService
{
    private readonly T _adapted;
    EventServiceAdapter(T adapted)
    {
        _adapted = adapted;
    }
    public string SomeMethod()
    {
         return _adapted.SomeMethod();
    }
}

然后在您注册的单例类型周围注册接口适配器。

_container
    .RegisterType<EventService>(new ContainerControlledLifetimeManager())
    .RegisterType<IEventService, EventServiceAdapter<EventService>>("namedEventService");

然后,您可以将任何单例隐藏在任意数量的接口后面,并同时使用Resolve和ResolveAll。

以上就是短码网小编为大家整理的《Unity将两个接口注册为一个单例》相关内容,希望大家喜欢。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。

如若内容造成侵权/违法违规/事实不符,请将联系本站反馈,一经查实,立即处理!

Unity将两个接口注册为一个单例》文档下载仅供参考学习,下载后请在24小时内删除。

转载注明出处:https://www.duanma.net/article/3c0f59bc862.html

回到顶部