在框架中使用 Func 代替实例

发布于 2024-10-19 17:59:12 字数 752 浏览 3 评论 0原文

当查看几个项目的源代码时,我发现了一个我不太理解的模式。 例如在 FubuMVC公共服务定位器 a Func 在静态提供者更改时使用。 谁能解释一下使用:

private static Func<IServiceLocator> currentProvider;
public static IServiceLocator Current
{
   get { return currentProvider(); }
}

public static void SetLocatorProvider(Func<IServiceLocator> newProvider)
{
   currentProvider = newProvider;
}

而不是:有什么好处?

private static IServiceLocator current;
public static IServiceLocator Current
{
   get { return current; }
}

public static void SetLocator(IServiceLocator newInstance)
{
   current = newInstance;
}

When looking at the source code of a couple of projects I found a pattern I can not quite understand.
For instance in FubuMVC and Common Service Locator a Func is used when a static provider is changed.
Can anyone explain what the benefit is of using:

private static Func<IServiceLocator> currentProvider;
public static IServiceLocator Current
{
   get { return currentProvider(); }
}

public static void SetLocatorProvider(Func<IServiceLocator> newProvider)
{
   currentProvider = newProvider;
}

instead of:

private static IServiceLocator current;
public static IServiceLocator Current
{
   get { return current; }
}

public static void SetLocator(IServiceLocator newInstance)
{
   current = newInstance;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

养猫人 2024-10-26 17:59:13

第一个模型相对于第二个模型的主要优点是所谓的“延迟初始化”。在第二个示例中,一旦调用 SetLocator,您就必须将 IServiceLocator 实例加载到内存中并准备就绪。如果创建此类实例的成本很高,和/或与一堆其他对象一起创建(例如在应用程序启动时),那么最好尝试延迟对象的实际创建以减少对用户的明显延迟。另外,如果依赖类可能不使用依赖项(假设它只用于某些操作,并且该类可以执行不需要依赖项的其他操作),则实例化一个依赖项将是一种浪费。

解决方案是提供“工厂方法”而不是实际实例。当实际需要实例时,会调用工厂方法,并在使用前的最后一刻创建实例。这减少了前端加载时间并避免创建不需要的依赖项。

The major advantage of the first model over the second is what's called "lazy initialization". In the second example, as soon as SetLocator is called, you must have an IServiceLocator instance loaded in memory and ready to go. If such instances are expensive to create, and/or created along with a bunch of other objects at once (like on app startup), it's a good idea to try to delay actual creation of the object to reduce noticeable delays to the user. Also, if the dependency may not be used by the dependent class (say it's only needed for certain operations, and the class can do other things that don't require the dependency), it would be a waste to instantiate one.

The solution is to provide a "factory method" instead of an actual instance. When the instance is actually needed, the factory method is called, and the instance is created at the last possible moment before it's used. This reduces front-end loading times and avoids creating unneeded dependencies.

水波映月 2024-10-26 17:59:13

@KeithS 的回答很好。这里需要注意的另一件事是在某些实例的初始化背后发生的事情。保留对故意易失性对象的引用可能很棘手。

例如,FubuMVC 针对每个 HTTP 请求启动一个嵌套的 StructureMap 容器,该容器将所有服务位置限制在该特定请求范围内。如果您有在已构建的管道中运行的类,您将需要使用通过 IServiceLocator 的该实例提供的上下文注入。

Good answer by @KeithS. Another thing to note here is what happens under the covers of the initialization of certain instances. Keeping a reference to intentionally volatile objects can be tricky.

FubuMVC, for instance, spins up a nested StructureMap container per HTTP request which scopes all service location to that specific request. If you have classes running within that pipeline that have been built up, you'll want to use the contextual injection provided to you via THAT instance of IServiceLocator.

蓦然回首 2024-10-26 17:59:13

newProvider 的实现者有更多的灵活性。他们可以延迟加载、异步加载(然后,如果在调用 func 时尚未加载,则可以有代码等待),他们可以允许它根据运行时参数等进行更改。

Theres a lot more flexibility to the implementer of newProvider. They can lazy load, async load (and and then if it's not loaded by the time the func is called it can have code to wait), they can allow it change based on runtime parameters etc.

清君侧 2024-10-26 17:59:13

func 允许执行多种操作

  1. 定位器的创建可以延迟到需要时为止。因此它是懒惰的。
  2. 提供者对象不包含任何状态。它不负责关闭定位器,除了在需要时返回当前定位器之外,它不会对其执行任何操作。
  3. 当定位器在运行时重新配置或决定需要不同的实例时,只要调用代码不存储对定位器的引用,它就可以控制定位器的生命周期。
  4. 由于定位器是由一种方法返回的,因此它具有更大的灵活性,例如创建线程本地定位器,因此它可以在每个线程中创建许多对象,而无需协调一个全局对象中的对象创建,这在涉及许多线程时可能会成为瓶颈。

我相信设计师所做的可以给你比我更多的观点,为什么抽象出“简单”的东西(比如返回服务定位器的实例)是一个好主意。

你的,
阿洛伊斯·克劳斯

A func allows several things

  1. The locator creation can be delayed until it is needed. It is therefore lazy.
  2. The provider object does not contain any state. It is not its responsiblity to shut down the locator does anything with it except to return the current locator when needed.
  3. When the locator is reconfigured at run time or it decides that a different instance is needed it can control the lifetime of the locator as long as the calling code does not store a reference to locator.
  4. Since the locator is returned by a method it has more flexibility e.g. to create a thread local locator so it can create many objects in each thread without the need to coordinate object creation in one global object which could become a bottleneck when many threads are involved.

I am sure the designers did could give you more points than I did why it can be a good idea to abstract away "simple" things like to return an instance of a service locator.

Yours,
Alois Kraus

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文