- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在使用简单注入器通过构造函数注入将依赖项注入到我的对象中。
对于一组特定的对象(所有对象都从一个通用的抽象基类派生),我注入了一个工厂而不是具体对象,以便可以在运行时确定应注入哪个派生实例。工厂和单个实例在容器中注册为单例。
将所有对象注册到DI容器后,我调用Container.Verify()方法来验证我的配置。问题是,此方法的实现会创建向容器注册的每种类型的实例。这些派生的实例创建起来很昂贵,并且它们的创建有副作用(它们来自正在更新以使用DI的旧代码)。从长远来看,我会摆脱副作用,但从短期来看,这是不可行的。
如何告诉容器不要验证这些派生实例?
我想保留Verify()调用(至少对于调试版本而言),但是不能接受Verify()调用实例化的这些实例。此外,它们需要在Singleton Lifestyle中注册,所以我不能只在容器中注册它们。
我想出的一个解决方案是不将派生对象注册到容器中(从而使它们不可验证),然后让(Singleton Lifestyle)Factory实现缓存它创建的第一个实例。它可以工作,但是很脏,如果有人在其他地方(不太可能)显式请求派生类型的实例,则将创建一个新实例(因为默认的Lifestyle是Transient)。
这是我拥有的类结构的示例:
public class AbstractBase { }
public class Derived1 : AbstractBase { }
public class Derived2 : AbstractBase { }
public class Derived3 : AbstractBase { }
public class MyFactory
{
private readonly Func<Derived1> _factory1;
private readonly Func<Derived2> _factory2;
private readonly Func<Derived3> _factory3;
public MyFactory(Func<Derived1> factory1, Func<Derived2> factory2, Func<Derived3> factory3)
{
_factory1 = factory1;
_factory2 = factory2;
_factory3 = factory3;
}
public AbstractBase Create()
{
if (AppSettings.ProductType == ProductType.Type1)
return _factory1();
if (AppSettings.ProductType == ProductType.Type2)
return _factory2();
if (AppSettings.ProductType == ProductType.Type3)
return _factory3();
throw new NotSupportedException();
}
}
Container container = new Container();
container.RegisterSingle<Derived1>();
container.RegisterSingle<Derived2>();
container.RegisterSingle<Derived3>();
container.RegisterSingle<Func<Derived1>>(() => container.GetInstance<Derived1>());
container.RegisterSingle<Func<Derived2>>(() => container.GetInstance<Derived2>());
container.RegisterSingle<Func<Derived3>>(() => container.GetInstance<Derived3>());
container.RegisterSingle<MyFactory>();
container.Verify(); // <-- will instantiate new instances of Derived1, Derived2, and Derived3. Not desired.
最佳答案
根据您的问题,我知道您非常了解当前方法的弊端,并且当前正在处理一些无法在单个迭代中更改的旧代码。但是由于其他人也会读这篇文章,所以我想通常记下injection constructors should be simple, fast and reliable。
这样一来,就可以回答问题:不,没有办法将注册标记为跳过在Simple Injector中注册的方式。
在调用InstanceProducer
之前为容器创建的所有Verify()
实例都将得到验证(除非之前已对其进行垃圾回收)。通常,在调用InstanceProducer
重载时会为您隐式创建Register
实例,但是您也可以通过调用InstanceProducer
创建新的Lifestyle.CreateProducer
实例。这些生产者将不属于任何对象图(这意味着Simple Injector不会使用它们来自动关联其他类型),它们将充当根类型。但是,容器仍会跟踪这些生产者,并且验证也将应用于它们。
因此,这里的技巧是在验证过程之后触发创建新的InstanceProducer
实例。您可以通过调用Lifestyle.CreateProducer
来执行此操作,也可以通过解析未注册的具体类型来执行此操作,如您在示例中所做的那样。解决未注册类型的缺点当然是默认情况下将其解析为瞬态。有两种解决方法。您可以自己缓存实例,也可以指示容器将特定类型创建为单例。
自己进行缓存可能看起来像这样:
var lazy1 = new Lazy<Derived1>(container.GetInstance<Derived1>);
container.RegisterSingle<Func<Derived1>>(() => lazy1.Value);
// Custom lifestyle selection behavior
public class AbstractBaseDerivativesAsSingleton : ILifestyleSelectionBehavior {
public Lifestyle SelectLifestyle(Type serviceType, Type implementationType) {
typeof(AbstractBase).IsAssignableFrom(implementationType)
? Lifestyle.Singleton
: Lifestyle.Transient;
}
}
// Usage
var container = new Container();
container.Options.LifestyleSelectionBehavior =
new AbstractBaseDerivativesAsSingleton();
container.RegisterSingle<Func<Derived1>>(() => container.GetInstance<Derived1>());
InstanceProducers
调用自己创建
Lifestyle.CreateProducer
。由于需要单例,因此必须调用
Lifestyle.Singleton.CreateProducer
。这些生产者需要在调用之后创建以进行验证,因此您仍然需要使用Lazy作为延迟机制:
// This factory should be part of your composition root,
// because it now depends on the container.
public class MyFactory : IMyFactory
{
private readonly Container container;
private readonly Dictionary<ProductType, Lazy<InstanceProducer>> producers;
public MyFactory(Container container) {
this.container = container;
this.producers = new Dictionary<ProductType, Lazy<InstanceProducer>>
{
{ProductType.Type1, new Lazy<InstanceProducer>(this.CreateProducer<Derived1>)},
{ProductType.Type2, new Lazy<InstanceProducer>(this.CreateProducer<Derived2>)},
{ProductType.Type3, new Lazy<InstanceProducer>(this.CreateProducer<Derived3>)}
};
}
public AbstractBase Create() {
return (AbstractBase)this.producers[AppSettings.ProductType].GetInstance()
}
private InstanceProducer CreateProducer<T>() where T : AbstractBase {
Lifestyle.Singleton.CreateProducer<AbstractBase, T>(this.container);
}
}
public class AbstractBaseAppSettingsSwitchProxy : AbstractBase
{
private readonly IMyFactory factory;
public AbstractBaseAppSettingsSwitchProxy(IMyFactory factory) {
this.factory = factory;
}
public override void SomeFunction() {
this.factory.Create().SomeFunction();
}
}
AbstractBase
进行通信,就好像总是有一个。这可以使您的应用程序代码更简洁,使用者代码更简单,并使使用者更易于测试。
AbstractBase
的结构,这些解决方案可能不适用于您。如果您有一个胖的基类,并且其中的某些方法是虚拟的,而另一些则没有,那么这样做可能会非常困难。这些解决方案通常只能在设计良好(SOLID)的系统中很好地工作。但这实际上就是所有这些。我的经验是,没有SOLID代码,一切都会变得很麻烦。作为软件开发人员,我们的主要工作之一是降低软件的总体拥有成本,而做到这一点的最佳方法之一是将SOLID原理应用于我们的软件。
Container container = new Container();
container.RegisterSingle(typeof(AbstractBase, GetConfiguredAbstractBaseType()));
private static Type GetConfiguredAbstractBaseType() {
switch (AppSettings.ProductType) {
case ProductType.Type1: return typeof(Derived1);
case ProductType.Type2: return typeof(Derived2);
case ProductType.Type3: return typeof(Derived3);
default: throw new NotSupportedException();
}
}
public class LazyAbstractBaseProxy : AbstractBase
{
private readonly Lazy<AbstractBase> lazy;
public LazyAbstractBaseProxy(Lazy<AbstractBase> lazy) {
this.lazy = lazy;
}
public override void SomeFunction() {
this.lazy.Value.SomeFunction();
}
}
Type type = GetConfiguredAbstractBaseType();
var lazy = new Lazy<InstanceProducer>(() =>
Lifestyle.Singleton.CreateProducer(typeof(AbstractBase), type, container));
container.RegisterSingle<AbstractBase>(new LazyAbstractBaseProxy(
new Lazy<AbstractBase>(() => (AbstractBase)lazy.Value.GetInstance()));
Type type = GetConfiguredAbstractBaseType();
var lazy = new Lazy<InstanceProducer>(() =>
Lifestyle.Singleton.CreateProducer(typeof(AbstractBase), type, container));
container.RegisterSingle<Func<AbstractBase>>(() => (AbstractBase)lazy.Value.GetInstance());
关于c# - 简单注入(inject)器:如何跳过对容器中对象的验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31688864/
在 JSF2 应用程序中遇到验证属性的问题时,有两种主要方法。 使用 Annotation 在 ManagedBean 上定义验证 @ManagedBean public class MyBean {
我想实现一个不常见的功能,我认为 jquery 验证插件将是最好的方法(如果您在没有插件的情况下建议和回答,我们也会欢迎)。我想在用户在输入字段中输入正确的单词后立即隐藏表单。我试过这个: $("
我有几个下拉菜单(类名为month_dropdown),并且下拉菜单的数量不是恒定的。我怎样才能为它们实现 NotEqual 验证。我正在使用 jQuery 验证插件。 这就是我写的 - jQuery
我设法制作了这个网址验证代码并且它起作用了。但我面临着一个问题。我认为 stackoverflow 是获得解决方案的最佳场所。 function url_followers(){ var url=do
我目前正在使用后端服务,该服务允许用户在客户端应用程序上使用 Google Games 库登录。 用户可以通过他们的 gplay ID 向我们发送信息,以便登录或恢复旧帐户。用户向我们发送以下内容,包
我正在尝试验证输入以查看它是否是有效的 IP 地址(可能是部分地址)。 可接受的输入:172、172.112、172.112.113、172.112.113.114 Not Acceptable 输入
我从 Mongoose 验证中得到这条消息: 'Validator failed for path phone with value ``' 这不应该发生,因为不需要电话。 这是我的模型架构: var
我一直在尝试使用Python-LDAP (版本 2.4.19)在 MacOS X 10.9.5 和 Python 2.7.9 下 我想在调用 .start_tls_s() 后验证与给定 LDAP 服务
我正在处理一个仅与 IE6 兼容的旧 javascript 项目(抱歉...),我想仅在 VS 2017 中禁用此项目的 ESLint/CSLint/Javascript 验证/CSS 验证。 我知道
我正在寻找一种方法来验证 Spring 命令 bean 中的 java.lang.Double 字段的最大值和最小值(一个值必须位于给定的值范围之间),例如, public final class W
我正在尝试在 springfuse(JavaEE 6 + Spring Framework (针对 Jetty、Tomcat、JBoss 等)) 和 maven 的帮助下构建我的 webapps 工作
我试图在我们的项目中使用 scalaz 验证,但遇到了以下情况: def rate(username: String, params: Map[String, String]): Validation
我有一个像这样的 Yaml 文件 name: hhh_aaa_bbb arguments: - !argument name: inputsss des
我有一个表单,人们可以单击并向表单添加字段,并且我需要让它在单击时验证这些字段中的值。 假设我单击它两次并获取 2 个独立的字段集,我需要旋转 % 以确保它在保存时等于 100。 我已放入此函数以使其
在我的页面中有一个选项可以创建新的日期字段输入框。用户可以根据需要创建尽可能多的“截止日期”和“起始日期”框。就像, 日期_to1 || date_from1 日期到2 ||日期_from2 date
我有一个像这样的 Yaml 文件 name: hhh_aaa_bbb arguments: - !argument name: inputsss des
有没有办法在动态字段上使用 jquery 验证表单。 我想将其设置为必填字段 我正在使用 Jsp 动态创建表单字段。 喜欢 等等...... 我想使用必需的表单字段验证此表单字段。 最佳答
嗨,任何人都可以通过提供 JavaScript 代码来帮助我验证用户名文本框不应包含数字,它只能包含一个字符。 最佳答案 使用正则表达式: (\d)+ 如果找到匹配项,则字符串中就有一个数字。 关于J
我有两个输入字段holidayDate和Description(id=tags) $(document).ready(function() {
我遇到了这个问题,这些验证从电子邮件验证部分开始就停止工作。 我只是不明白为什么即使经过几天的观察,只是想知道是否有人可以在这里指出我的错误? Javascript部分: function valid
我是一名优秀的程序员,十分优秀!