gpt4 book ai didi

c# - 依赖注入(inject)和初始化方法

转载 作者:行者123 更新时间:2023-11-30 22:15:32 24 4
gpt4 key购买 nike

我读了Miško Hevery's Guide: Writing Testable Code如果“构造函数完成后对象未完全初始化(注意初始化方法)”,它会发出警告标志。

假设我写了一个 Redis 包装类,它有一个接受主机名和端口的 init 方法。根据 Miško 的说法,这是一个警告信号,因为我需要调用它的 init 方法。

我正在考虑的解决方案如下:对于每个需要这种初始化的类,创建一个具有创建该类的 Create 方法的工厂类,并调用其 init 方法。

现在在代码中:而不是使用类似的东西:

class Foo
{
private IRedisWrapper _redis;
public Foo(IRedisWrapper redis)
{
_redis = redis;
}
}
....
IRedisWrapper redis = new RedisWrapper();
redis.init("localhost", 1234);
Foo foo = new Foo(redis);

我会使用类似的东西:

class Foo
{
private IRedisWrapper _redis;
public Foo(IRedisWrapper redis)
{
_redis = redis;
}
}
....
RedisWrapperFactory redisFactory = new RedisWrapperFactory();
IRedisWrapper redisWrapper = redisFactory.Create();
Foo foo = new Foo(redisWrapper);

我正在使用 Simple Injector 作为 IOC 框架,这使得上述解决方案成为问题 - 在这种情况下,我会使用类似的东西:

class Foo
{
private RedisWrapper _redis;
public Foo(IRedisWrapperFactory redisFactory)
{
_redis = redisFactory.Create();
}
}

我真的很想听听您对上述解决方案的意见。

谢谢

最佳答案

也许我误解了你的问题,但我不认为简单注入(inject)器是这里的限制因素。由于构造函数应尽可能少地执行操作,因此不应从构造函数中调用 Create 方法。这甚至是一件奇怪的事情,因为工厂旨在延迟类型的创建,但由于您在构造函数中调用 Create,因此创建不会延迟。

您的 Foo 构造函数应该简单地依赖于 IRedisWrapper 并且您应该将 redisFactory.Create() 调用提取到您的 DI 配置中,如下所示:

var redisFactory = new RedisWrapperFactory();

container.Register<IRedisWrapper>(() => redisFactory.Create());

但是由于工厂的唯一目的是防止在整个应用程序中出现重复的初始化逻辑,它现在失去了它的目的,因为使用工厂的唯一地方是在 DI 配置中。所以你可以把工厂扔出去写如下注册:

container.Register<IRedisWrapper>(() =>
{
IRedisWrapper redis = new RedisWrapper();
redis.init("localhost", 1234);
return redis;
});

您现在将 Create 方法的主体放在匿名委托(delegate)中。您的 RedisWrapper 类目前有一个默认构造函数,所以这种方法很好。但是如果 RedisWrapper 开始获得自己的依赖项,最好让容器创建该实例。这可以按如下方式完成:

container.Register<IRedisWrapper>(() =>
{
var redis = container.GetInstance<RedisWrapper>();
redis.init("localhost", 1234);
return redis;
});

当您需要在创建后初始化您的类时,正如 RedisWrapper 明确需要的那样,建议的方法是使用 RegisterInitializer 方法。最后一段代码可以写成如下:

container.Register<IRedisWrapper, RedisWrapper>();

container.RegisterInitializer<RedisWrapper>(redis =>
{
redis.init("localhost", 1234);
});

这注册了 RedisWrapper,当 IRedisWrapper 被请求时要返回,并且 RedisWrapper 是用注册的初始化程序初始化的。此注册可防止隐藏回调到容器。这提高了性能并提高了容器的能力 diagnose your configuration .

关于c# - 依赖注入(inject)和初始化方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17895542/

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