Using Funcs instead of instances within

When I look at the source code of several projects, I found a template that I cannot understand. For example, in FubuMVC and Shared Services Locator a Func used when the static provider changes. Can anyone explain what the benefits of using are:

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

instead:

 private static IServiceLocator current; public static IServiceLocator Current { get { return current; } } public static void SetLocator(IServiceLocator newInstance) { current = newInstance; } 
+4
source share
4 answers

The main advantage of the first model over the second is what is called "lazy initialization." In the second example, as soon as SetLocator is called, you should have an IServiceLocator instance loaded into memory and ready to go. If such instances are expensive to create and / or create together with a number of other objects at the same time (for example, when starting the application), it is recommended to try to postpone the actual creation of the object in order to reduce noticeable delays for the user. In addition, if the dependency cannot be used by the dependent class (say that it is necessary only for certain operations, and the class can do other things that do not require the dependency), it would be useless to create an instance.

The solution is to provide a "factory method" instead of the actual instance. When an instance is really needed, the factory method is called, and the instance is created at the last possible moment before it is used. This reduces foreground loading time and avoids unnecessary dependencies.

+9
source

Good answer from @KeithS. Another thing to note here is what happens under the cover of the initialization of certain instances. Keeping links to intentionally unstable objects can be tricky.

For example, FubuMVC spins a nested StructureMap container for each HTTP request that binds the entire service location to this specific request. If you have classes running in this pipeline that have been created, you will want to use the context injection provided to you through the THAT IServiceLocator instance.

+2
source

NewProvider has a lot more flexibility for the developer. They can use lazy load, asynchronous load (and then, if it does not load at the time func is called, it can have code to wait), they can let it change based on runtime parameters, etc.

+1
source

Func function allows several things

  • The creation of a locator can be delayed until it is needed. Therefore, he is lazy.
  • The provider object does not contain any state. It is not his duty to disconnect the locator, with anything except to return the current locator when necessary.
  • When a locator reconfigures at run time or decides that another instance is needed, it can control the lifetime of the locator if the calling code does not store a reference to the locator.
  • Since the locator is returned by the method, it has more flexibility, for example. to create a local thread locator so that it can create many objects in each thread without having to coordinate the creation of the object in one global object, which can become a bottleneck when many threads are involved.

I’m sure that designers could give you more points than I did, why it might be a good idea to abstract away β€œsimple” things, for example, return an instance of a service locator.

Regards, Alois Kraus

+1
source

Source: https://habr.com/ru/post/1342047/


All Articles