首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >TinyIoC和装饰器模式

TinyIoC和装饰器模式
EN

Stack Overflow用户
提问于 2013-07-03 23:15:55
回答 2查看 850关注 0票数 1

有没有人可以提供一个简单的例子,说明如何用TinyIoC实现装饰器模式

前面的question展示了如何在Ninject中使用以下内容执行此操作:

代码语言:javascript
复制
Bind<IRepository>().To<MoreAdvancedRespository>
               .WhenInjectedInto<TrickyRepository>();
Bind<IRepository>().To<SomeSimpleRepository>
               .WhenInjectedInto<MoreAdvancedRespository>();
EN

回答 2

Stack Overflow用户

发布于 2013-07-13 06:33:20

在尝试设置这个示例一段时间后,简短的答案是: TinyIoC不能正确地做到这一点,至少如果我们讨论的是传统意义上的“存储库”,并希望容器将它们视为单例。

这就是说,这种方式是有效的:

代码语言:javascript
复制
public interface IRepository { }

public class MoreAdvancedRepository : IRepository
{
    public MoreAdvancedRepository(IRepository innerRepository, ISomeOtherDependency otherDependency) { }
}

public class TrickyRepository : IRepository
{
    public TrickyRepository(IRepository innerRepository, ISomeOtherDependency otherDependency) { }
}

public class SimpleRepository : IRepository { }

public interface ISomeOtherDependency { }

public class SomeOtherDependencyWeasel : ISomeOtherDependency { }


// Register the other dependency
container.Register<ISomeOtherDependency, SomeOtherDependencyWeasel>();

// Register the "innermost" repository with a name
container.Register<IRepository, SimpleRepository>("simple");

// Register the inner decorator implementation, also with a name, and telling the container what to do for the dependency called "innerRepository"
container.Register<IRepository>((c, p) => c.Resolve<MoreAdvancedRepository>(new NamedParameterOverloads() { { "innerRepository", c.Resolve<IRepository>("simple") } }), "advanced");

// Register the outer decorator the same way, only without a name for the registration, so this will be what's resolved whenever IRepository is requested without specifying a name
container.Register<IRepository>((c, p) => c.Resolve<TrickyRepository>(new NamedParameterOverloads() { { "innerRepository", c.Resolve<IRepository>("advanced") } }));

// Resolve stuff to check how the registration worked out
var simple1 = container.Resolve<IRepository>("simple");
var simple2 = container.Resolve<IRepository>("simple");
var advanced1 = container.Resolve<IRepository>("advanced");
var advanced2 = container.Resolve<IRepository>("advanced");
var tricky1 = container.Resolve<IRepository>();
var tricky2 = container.Resolve<IRepository>();

Assert.IsType<SimpleRepository>(simple1); // this passes, unsurprisingly
Assert.Same(simple1, simple2); // this passes, too, as simple Register<TResolve, TImpl>() calls are implicitly .AsSingleton()
Assert.IsType<MoreAdvancedRepository>(advanced1); // passes
Assert.IsType<TrickyRepository>(tricky1); // passes

Assert.Same(advanced1, advanced2); // this fails, as Register<TResolve>(Func<TResolve, TinyIoCContainer, NamedParameterOverloads>) calls are implicitly .AsMultiInstance() and can not be changed to .AsSingleton() 
Assert.Same(tricky1, tricky2); // fails for the same reason

现在,人们可能会尝试通过这样做来欺骗容器(我就是):

代码语言:javascript
复制
container.Register<MoreAdvancedRepository>((c, p) => c.Resolve<MoreAdvancedRepository>(new NamedParameterOverloads() { { "innerRepository", c.Resolve<IRepository>("simple") } })); // always .AsMultiInstance()

container.Register<IRepository, MoreAdvancedRepository>("advanced"); // implicitly .AsSingleton(), so only one instance should be created and then returned for subsequent calls

然后可以将其包装在扩展方法中,以便在容器上再次具有单个方法调用。不幸的是,这不起作用-当尝试解析名为“IRepository”的高级注册时,容器显然找不到以前显式注册的MoreAdvancedRepository,并抛出一个TinyIoCResolutionException

因此,上面的方法在以下情况下可以工作:

  • 每种不同的存储库类型仅解析一次或
  • 每次解析特定存储库类型时都会创建一个新实例,这是没有问题的。

否则,对于这些类,您可能需要退回到可怜的DI,或者使用不同的IoC容器。

票数 2
EN

Stack Overflow用户

发布于 2013-07-04 03:00:44

你不能使用自动连接,所以你必须为每个装饰器注册一个lambda:

代码语言:javascript
复制
// Register the repository
container.Register<SomeSimpleRepository>();

// Register the inner decorator
container.Register<MoreAdvancedRespository>(() => new MoreAdvancedRespository(
    container.Resolve<SomeSimpleRepository>(),
    container.Resolve<ISomeOtherDependency>()));

// Register the outer decorator
container.Register<IRepository>(() => new TrickyRepository(
    container.Resolve<MoreAdvancedRespository>(),
    container.Resolve<ISomeOtherDependency>()));

您必须对系统中的每个存储库重复此操作。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17451821

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档