结构图和创建具有初始状态的对象
我有一个需要向其中注入依赖项的对象
public class FootballLadder
{
public FootballLadder(IMatchRepository matchRepository, int round)
{
// set initial state
this.matchRepo = matchRepository;
this.round = round;
}
public IEnumerable<LadderEntry> GetLadderEntries()
{
// calculate the ladder based on matches retrieved from the match repository
// return the calculated ladder
}
private IMatchRepository matchRepo;
private int round;
}
。出于参数考虑,我们假设我无法将 round 参数传递到 GetLadderEntries 调用本身。
使用 StructureMap,如何注入对 IMatchRepository 的依赖并设置初始状态?或者这是与框架作斗争的情况之一是代码应该重构的标志吗?
I have an object which needs a dependency injected into it
public class FootballLadder
{
public FootballLadder(IMatchRepository matchRepository, int round)
{
// set initial state
this.matchRepo = matchRepository;
this.round = round;
}
public IEnumerable<LadderEntry> GetLadderEntries()
{
// calculate the ladder based on matches retrieved from the match repository
// return the calculated ladder
}
private IMatchRepository matchRepo;
private int round;
}
For arguments sake, lets assume that I can't pass the round parameter into the GetLadderEntries call itself.
Using StructureMap, how can I inject the dependency on the IMatchRepository and set the initial state? Or is this one of those cases where struggling against the framework is a sign the code should be refactored?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您始终可以使用构造函数参数作为默认值。我将以下内容用于 sqlconnection 的默认实例。
还有其他方法,但我记不起来了。
编辑:这也是可以完成的另一种方法。我从这里找到了这个:
http://www.theabsent Mindcoder.com/2010/05 /struct-map-26-constructor-arguments.html
如果 round 的值是通过方法确定的,您可以使用 lambda 表达式指定它来加载值,如下所示
希望这是有道理的。但要回答你的问题,是的,这是可能的,而且很容易。
You can always use constructor parameters for default values. I used the following for a default instance of a sqlconnection.
There are other ways as well but I don't remember them off the top of my head.
EDIT: Here is another way it could be done as well. I found this one from here:
http://www.theabsentmindedcoder.com/2010/05/structure-map-26-constructor-arguments.html
If the value of round was determined from a method you could specify it with a lambda expression to load the value like so
Hope this makes sense. But to answer your question yes it is possible and pretty easily.
大多数 DI 框架允许您在构造函数中注入基元,如 Spinon 向您展示了。如果可能的话,我尝试以不需要复杂配置的方式重构我的代码。通常,这使我的应用程序代码最容易理解,并且意外最少(每分钟 WTF 数量很少;-))。您必须仔细平衡这一点,因为有时复杂的配置可能会使您的应用程序代码更简单。
以下是一些可能的重构建议:
1) 使用工厂:
当客户端必须控制
round
值时,使用工厂非常有用:这样您就可以注入
IFootballLadderFactory
并允许客户端调用:2) 使用属性:
您可以从构造函数中删除
round
参数并将其更改为 get/set 属性。当客户端必须能够控制round
值或使用工厂时,这都很有用:例如,
IFootballLadderFactory
的实现可能如下所示:或者客户端可以设置
Round
属性:请小心最后一个示例。客户端通常不必关心依赖项的生命周期。在本例中,我们正在更改注入依赖项的状态。这可以防止我们更改此依赖项的生命周期,因为在这种情况下,可以从客户端脚下更改
ladder
实例的状态。除此之外,当Round
从未设置时,FootballLadder
类应该抛出InvalidOperationException
。我认为这样的检查很好而且很干净,但确实会让你编写更多的代码。3) 将
IRoundProvider
注入到FootballLadder
构造函数中:正如 Spinon 所写,您可以实现
IRoundProvider
,但改为在配置中使用它时,您可以将其用作构造函数参数。4) 创建一个特定于您的 DI 配置的子类型:
现在您可以按如下方式注册它:
这样做的缺点是您拥有的额外代码本身是纯配置代码。除此之外,当
FootballLadder
的依赖项发生变化时,您也必须更改DIFootballLadder
。我希望这有帮助。
Most DI frameworks allow you to inject primitives in constructors as Spinon showed you. When possible, I try to refactor my code in a way that I don't need complex configurations. Often this makes my application code the most understandable, with the least surprises (low number of WTFs per minute ;-)). You have to balance this out carefully, because sometimes complex configurations could make your application code simpler.
Here are some possible suggestions for refactorings:
1) Use a factory:
Using a factory is useful when clients must control the
round
value:This way you can inject a
IFootballLadderFactory
and allow clients to call:2) Use a property:
You can remove the
round
argument from the constructor and change it in to a get/set property. This is both useful when clients must be able to control theround
value or when using a factory:And implementation of the
IFootballLadderFactory
for instance could look like this:Or a client could set the
Round
property:Please be careful with this last example. The client should normally not have to care about the lifetime of the dependency. In this case, we're changing the state of an injected dependency. This prevents us from changing the lifetime of this dependency, because in that case the state of the
ladder
instance, could be changed from under the client's feet. Besides this, theFootballLadder
class should throw anInvalidOperationException
when theRound
was never set. I think such a check is nice and clean, but does make you write a bit more code.3) Inject a
IRoundProvider
into theFootballLadder
constructor:As Spinon wrote, you can implement a
IRoundProvider
, but instead of using it in your configuration, you can use it as constructor argument.4) Create a sub type specific for your DI configuration:
Now you can register the it as follows:
Downside of this is that you have this extra code with itself is plain configuration code. Besides that, when the dependencies of the
FootballLadder
change, you have to change theDIFootballLadder
as well.I hope this helps.