- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
这是一个相当直接的装饰器模式场景,复杂的是装饰类型有一个构造函数参数,该参数取决于它被注入(inject)的类型。
我有一个这样的界面:
interface IThing
{
void Do();
}
像这样的实现:
class RealThing : IThing
{
public RealThing(string configuration)
{
... implementation ...
}
public void Do()
{
... implementation ...
}
}
还有这样的装饰器:
class DecoratingThing : IThing
{
IThing _innerThing;
public DecoratingThing(IThing thing)
{
_innerThing = thing;
}
public void Do()
{
_innerThing.Do();
}
}
最后,我有一些类型需要 IThing
, 称为 Depender1
, Depender2
等..
class DependerX()
{
public DependerX(IThing thing)
{
... implementation ...
}
}
我想配置一个 IOC 容器来解析 DependerX
的实例这样他们就会被注入(inject) RealThing
用 DecoratingThing
装饰. 重要:每个DependerX
type 需要不同的值 configuration
传递给其 RealThing
的构造函数, 在每种情况下都说“ConfigX”。例如IoC 容器完成的工作可能是:
new Depender1(new DecoratingThing(new RealThing("Config1")));
new Depender2(new DecoratingThing(new RealThing("Config2")));
...等等。
在 Unity 中,这似乎很难配置,因为我必须将装饰器与装饰器混合使用:
container.RegisterType<IThing, DecoratingThing>("ConfigX",
new InjectionFactory(container => new DecoratingThing(new RealThing("ConfigX"));
container.RegisterType<DependerX>(
new InjectionConstructor(new ResolvedParameter<IThing>("ConfigX");
然后重复,很好地违反 DRY,对于每个 DependerX
.
我想做的是消除嵌入 RealThing
结构的需要在建DecoratingThing
在 IThing
的每个命名注册中- 只声明装饰一次。例如,如果将来需要更 retrofit 饰,则重新配置会更容易。我想到的最好的方法是这个注册辅助方法:
void RegisterDepender<TDepender>(IUnityContainer container, string config)
{
container.RegisterType<TDepender>(new InjectionConstructor(
new ResolvedParameter<IThing>(config)));
container.RegisterType<IThing, DecoratingThing>(config,
new InjectionFactory(c => new DecoratingThing(new RealThing(config))));
}
这至少消除了重复,但我仍然必须嵌入 RealThing
的结构在DecoratingThing
里面- 这意味着我不能独立地改变他们的生命周期。我无法注册 IThing
再次这样做是因为我已经用完了该接口(interface)的名称注册。如果我想这样做,我必须像这样引入另一组命名实例:
void RegisterDepender<TDepender>(IUnityContainer container, string config)
{
string realConfig = "Real" + config;
container.RegisterType<TDepender>(new InjectionConstructor(
new ResolvedParameter<IThing>(config)));
container.RegisterType<IThing, DecoratingThing>(config,
new InjectionFactory(c => new DecoratingThing(
container.Resolve<IThing>(realConfig))));
container.RegisterType<IThing, RealThing>(realConfig,
new ContainerControlledLifetimeManager(),
new InjectionConstructor(config));
}
这真的是最好的选择吗?对于那些想要理解的人来说,这感觉很复杂,而且可能很难。其他 IoC 容器是否有令人信服的方式来涵盖这种情况?由于每个 DependerX 的注入(inject)工作模式都是重复的,有没有办法只在顶层 ( DependerX
) 级别使用命名实例?
还有其他意见吗?
最佳答案
类设计本身似乎是合理的。下面是一个基于约定的容器配置,基本上是这样做的:
public class MyConventions : UnityContainerExtension
{
protected override void Initialize()
{
var dependers = from t in typeof(IThing).Assembly.GetExportedTypes()
where t.Name.StartsWith("Depender")
select t;
foreach (var t in dependers)
{
var number = t.Name.TrimStart("Depender".ToArray());
var realName = "Real" + number;
var decoName = "Deco" + number;
var config = "Config" + number;
this.Container.RegisterType<IThing, RealThing>(realName,
new InjectionConstructor(config));
this.Container.RegisterType<IThing, DecoratingThing>(decoName,
new InjectionConstructor(
new ResolvedParameter<IThing>(realName)));
this.Container.RegisterType(t,
new InjectionConstructor(
new ResolvedParameter<IThing>(decoName)));
}
}
}
这个配置会自动添加所有匹配上述谓词的类,所以一旦你设置好了,你可以添加更多的类(比如 Depender4
或 Depender5
) 而无需重新访问容器配置。
以上配置满足这些单元测试:
[Fact]
public void ContainerCorrectlyResolvesDepender1()
{
var container = new UnityContainer().AddNewExtension<MyConventions>();
var actual = container.Resolve<Depender1>();
var deco = Assert.IsAssignableFrom<DecoratingThing>(actual.Thing);
var thing = Assert.IsAssignableFrom<RealThing>(deco.Thing);
Assert.Equal("Config1", thing.Configuration);
}
[Fact]
public void ContainerCorrectlyResolvesDepender2()
{
var container = new UnityContainer().AddNewExtension<MyConventions>();
var actual = container.Resolve<Depender2>();
var deco = Assert.IsAssignableFrom<DecoratingThing>(actual.Thing);
var thing = Assert.IsAssignableFrom<RealThing>(deco.Thing);
Assert.Equal("Config2", thing.Configuration);
}
[Fact]
public void ContainerCorrectlyResolvesDepender3()
{
var container = new UnityContainer().AddNewExtension<MyConventions>();
var actual = container.Resolve<Depender3>();
var deco = Assert.IsAssignableFrom<DecoratingThing>(actual.Thing);
var thing = Assert.IsAssignableFrom<RealThing>(deco.Thing);
Assert.Equal("Config3", thing.Configuration);
}
关于c# - 配置 Unity 以解析采用修饰依赖项的类型,该依赖项的参数随注入(inject)的类型而变化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9004297/
我在使用 lambda 表达式时遇到问题,该表达式用于自定义过滤来自 DataGridView 的数据。 这是表达式: private static Expression> ExpressionLon
我想使用装饰器模式扩展 basic_streambuf 对象的行为。这就是我目前得到的: template class forwarding_basic_streambuf : boost::
我正在编写一个 Backbone 应用程序,我想编写一个经过身份验证的装饰器,我可以用它来装饰路由器类中的方法(路由)列表。 所以我有一个带有几种方法的路由器,并尝试过类似的方法。但是,当我调用我想要
我想重写 alert() Javascript 函数,同时保留它的“聚焦”行为。即,自定义方面,同时将焦点带到打开弹出窗口的浏览器选项卡。 最佳答案 无法直接自定义/装饰 JavaScript 警报框
我们如何在 jquery mobile 中实现事件行为内部的 touch up。 我希望它的行为与 native ios 按钮完全相同。我们可以点击并按住点击并在按钮内移动手指只有当我在按钮内释放时才
我正在尝试覆盖模块(connect-mongo)中的类。该模块的工作原理大致如下: 在server.js中: const session = require('express-session'); c
我希望使用托管代码在非托管 C++ DLL 上加载库,然后在已损坏的外部函数上调用 GetProcAddress。我的问题是,您从 C++ 编译器获得的错位名称是否具有确定性?即:如果原始签名未更改,
为什么我不能使用 @staticmethod 装饰器使类的 __call__ 方法静态化? class Foo(object): @staticmethod def bar():
我有一个小的 Delphi 10.3.3 应用程序,它有一些文本编辑功能,使用用户输入文本的 TMemo。 我正在尝试包含一些格式选项,如本网站提供的内容: http://qaz.wtf/u/conv
这是我关于使用 Swift 运行的 iOS 应用程序的情况。 我有一个下载按钮,触摸后即可开始下载文件: @IBAction func downloadButtonPressed() { if
我有一个 View ,我需要检测一个属性是否用隐藏输入装饰。 我的属性(property)被定义为: [HiddenInput(DisplayValue = false)] public string
我在我的 Qt 应用程序中绘制线和点,但在 QPainter 中似乎存在缩放错误时遇到了问题。我的线条工作得很好,但点会受到某些缩放转换的影响,尽管笔被设置为“化妆品”。最让我困扰的是似乎只有一个轴(
我在 Eclipse 中遇到 Java 语法着色问题。我正在尝试更改 Eclipse 中 JUST java 修饰符的文本颜色(如公共(public)、 protected 、私有(private))
我在站点上有一些限制区域,我想为其指定 login_required 装饰器。但是我想在主 urls.py 中每次包含一次,而不是包含 urls.py 中的每个单独的 url 所以代替: /priva
这个建议似乎很有意义,因为该方法中没有使用 self,但现在我很好奇: 这是对 CBV 的疏忽吗?用户应该手动装饰每个 @staticmethod? Django 中是否已经有一些代码可以自动使所有
python 3.3:我可以装饰一个函数来忽略所有与命名参数不匹配的位置参数吗? import functools def ignore_star_args(): def wrapper(fu
我是一名优秀的程序员,十分优秀!