具有状态构造函数参数的 Akka .NET 中的依赖注入
Dependency Injection in Akka .NET with state constructor parameters
在构造函数中使用类似字符串参数的东西会使依赖注入变得非常混乱。认为:
public class CurrencyActor
{
public CurrencyActor(string currency, IRepository repository)
{
...
还有其他问题(例如this one)来解决这个依赖注入的特殊问题。通常这可以通过重新思考设计和重构来解决。
但是,如果让一个对象的多个版本分别负责不同的数据(例如,每种货币对应一个 CurrencyActor)真的有意义怎么办?这在使用 Akka .NET 等角色模型时非常正常,但即使在该域之外也是有意义的。
在传递所需的初始状态时使用依赖注入创建这些多个实例的最佳方法是什么?
在构造函数中有依赖关系并不麻烦,它非常非常普遍。这没有错。
您可以在接受您的依赖项的 CurrencyActor 上创建默认道具静态方法:
public static Props CreateProps(string currency, Irepository repo)
{
return Props.Create(() => new CurrrncyActor(currency, repo));
}
然后创建任意数量:
var usCurrency = system.ActorOf(CurrencyActor.CreateProps("US", someRepo), "US");
var swedishCurrency = system.ActorOf(CurrencyActor.CreateProps("SEK", someRepo), "SEK");
[更新]
关于在 Akka 中使用 DI 容器,这被列为否。人们在使用 akka.net
时犯的前 7 个错误中的 2 个
https://petabridge.com/blog/top-7-akkadotnet-stumbling-blocks/
Thus it’s considered to be a good practice for actors to manage their own dependencies, rather than delegate that work to a DI framework.
所以基本不做。如果你必须,根据那篇文章,Autofac 是最好的选择
[更新 2]
如果您想动态创建同一个 Actor 的新实例但要更改一些初始状态,那么您可以让主管负责创建它们:
public class MatchesSupervisor : ReceiveActor
{
List<IActorRef> _matches = new List<IActorRef>();
public void MatchesSupervisor()
{
Receive<SomeCommandToStartANewMatch>(msg =>
{
// store the currently active matches somewhere, maybe on a FullTime message they would get removed?
_matches.Add(Context.ActorOf(MatchActor.Create(msg.SomeMatchId)));
}
}
}
在上面的例子中,没有使用 DI 容器,如果每个 MatchActor 需要其他东西,比如 IRepository,那么它会在创建时传递给 MatchesSupervisor,然后在创建时传递给每个 MatchActor他们被创造了。
这在某种程度上也取决于状态的来源,以及开始新匹配的机制是什么 - 我只是假设其他 Actor 正在发送消息。
(我在 ipad 上打字,所以上面的代码可能不会真正编译,但希望你明白了,我也遗漏了 MatchActor 的实现,但它只是一个 Actor一些值传递给它的构造函数)
希望对您有所帮助!
在构造函数中使用类似字符串参数的东西会使依赖注入变得非常混乱。认为:
public class CurrencyActor
{
public CurrencyActor(string currency, IRepository repository)
{
...
还有其他问题(例如this one)来解决这个依赖注入的特殊问题。通常这可以通过重新思考设计和重构来解决。
但是,如果让一个对象的多个版本分别负责不同的数据(例如,每种货币对应一个 CurrencyActor)真的有意义怎么办?这在使用 Akka .NET 等角色模型时非常正常,但即使在该域之外也是有意义的。
在传递所需的初始状态时使用依赖注入创建这些多个实例的最佳方法是什么?
在构造函数中有依赖关系并不麻烦,它非常非常普遍。这没有错。
您可以在接受您的依赖项的 CurrencyActor 上创建默认道具静态方法:
public static Props CreateProps(string currency, Irepository repo)
{
return Props.Create(() => new CurrrncyActor(currency, repo));
}
然后创建任意数量:
var usCurrency = system.ActorOf(CurrencyActor.CreateProps("US", someRepo), "US");
var swedishCurrency = system.ActorOf(CurrencyActor.CreateProps("SEK", someRepo), "SEK");
[更新]
关于在 Akka 中使用 DI 容器,这被列为否。人们在使用 akka.net
时犯的前 7 个错误中的 2 个https://petabridge.com/blog/top-7-akkadotnet-stumbling-blocks/
Thus it’s considered to be a good practice for actors to manage their own dependencies, rather than delegate that work to a DI framework.
所以基本不做。如果你必须,根据那篇文章,Autofac 是最好的选择
[更新 2]
如果您想动态创建同一个 Actor 的新实例但要更改一些初始状态,那么您可以让主管负责创建它们:
public class MatchesSupervisor : ReceiveActor
{
List<IActorRef> _matches = new List<IActorRef>();
public void MatchesSupervisor()
{
Receive<SomeCommandToStartANewMatch>(msg =>
{
// store the currently active matches somewhere, maybe on a FullTime message they would get removed?
_matches.Add(Context.ActorOf(MatchActor.Create(msg.SomeMatchId)));
}
}
}
在上面的例子中,没有使用 DI 容器,如果每个 MatchActor 需要其他东西,比如 IRepository,那么它会在创建时传递给 MatchesSupervisor,然后在创建时传递给每个 MatchActor他们被创造了。
这在某种程度上也取决于状态的来源,以及开始新匹配的机制是什么 - 我只是假设其他 Actor 正在发送消息。
(我在 ipad 上打字,所以上面的代码可能不会真正编译,但希望你明白了,我也遗漏了 MatchActor 的实现,但它只是一个 Actor一些值传递给它的构造函数)
希望对您有所帮助!