Service Locator Pattern in C# with Lazy Initialization(转)
2011-03-07 15:18
519 查看
原文
In my previous post Service Locator Pattern in C#: A Simple Example I introduced a fairly basic implementation of this pattern. In this post I will address one of the limitations of that implementation, introducing a form of lazy initialization.
Defining Lazy Initialization
Lazy initialization improves the performance of object creation, deferring long running initializations until they are really needed.
Suppose for example that some of the fields of an object need to be read from the database. If a client never access those fields, accessing the database to retrieve those fields has been useless and it has just made object initialization slower (often by a considerable factor).
Martin Fowler credits Kent Beck with the introduction of the lazy initialization pattern, and in PoEAA book he describes it in the following way:
The basic idea is that every access to the field checks to see if it’s null. If so, it calculates the value of the field before returning the field. To make this work you have to ensure that the field is self-encapsulated, meaning that all access to the field, even from within the class, is done through a getting method.
Fairly simple.
The Improved Service Locator
The following is the improved version of the service locator which uses lazy initialization of the services.
We are now maintaining two separate maps:
Both maps are initialized in the constructor. However only the first map is filled. Every time
For this to work, the service implementation needs to expose a default (parameterless) constructor.
If services creation time is significant, lazy initialization can save you quite some time during application start up, with very little cost in terms of increased complexity.
Next article in the series: A Singleton Service Locator
In my previous post Service Locator Pattern in C#: A Simple Example I introduced a fairly basic implementation of this pattern. In this post I will address one of the limitations of that implementation, introducing a form of lazy initialization.
Defining Lazy Initialization
Lazy initialization improves the performance of object creation, deferring long running initializations until they are really needed.
Suppose for example that some of the fields of an object need to be read from the database. If a client never access those fields, accessing the database to retrieve those fields has been useless and it has just made object initialization slower (often by a considerable factor).
Martin Fowler credits Kent Beck with the introduction of the lazy initialization pattern, and in PoEAA book he describes it in the following way:
The basic idea is that every access to the field checks to see if it’s null. If so, it calculates the value of the field before returning the field. To make this work you have to ensure that the field is self-encapsulated, meaning that all access to the field, even from within the class, is done through a getting method.
Fairly simple.
The Improved Service Locator
The following is the improved version of the service locator which uses lazy initialization of the services.
internal class ServiceLocator : IServiceLocator { // a map between contracts -> concrete implementation classes private IDictionary<Type, Type> servicesType; // a map containing references to concrete implementation already instantiated // (the service locator uses lazy instantiation). private IDictionary<Type, object> instantiatedServices; internal ServiceLocator() { this.servicesType = new Dictionary<Type, Type>(); this.instantiatedServices = new Dictionary<Type, object>(); this.BuildServiceTypesMap(); } public T GetService<T>() { if (this.instantiatedServices.ContainsKey(typeof(T))) { return (T)this.instantiatedServices[typeof(T)]; } else { // lazy initialization try { // use reflection to invoke the service ConstructorInfo constructor = servicesType[typeof(T)].GetConstructor(new Type[0]); Debug.Assert(constructor != null, "Cannot find a suitable constructor for " + typeof(T)); T service = (T)constructor.Invoke(null); // add the service to the ones that we have already instantiated instantiatedServices.Add(typeof(T), service); return service; } catch (KeyNotFoundException) { throw new ApplicationException"The requested service is not registered"); } } } private void BuildServiceTypesMap() { servicesType.Add(typeof(IServiceA), typeof(ServiceA)); servicesType.Add(typeof(IServiceB), typeof(ServiceB)); servicesType.Add(typeof(IServiceC), typeof(ServiceC)); } }
We are now maintaining two separate maps:
servicesTypemaps an interface describing a service to a type T that implements that interface.
instantiatedServicesmaps an interface to an instantiated object of class T.
Both maps are initialized in the constructor. However only the first map is filled. Every time
GetServiceis invoked, we check whether a concrete implementation of that service has already been created. If not, we create that service implementation retrieving its constructor via reflection, and we put a reference to that implementation in the
instantiatedServicesmap.
For this to work, the service implementation needs to expose a default (parameterless) constructor.
If services creation time is significant, lazy initialization can save you quite some time during application start up, with very little cost in terms of increased complexity.
Next article in the series: A Singleton Service Locator
相关文章推荐
- Service Locator Pattern in C#: A Simple Example(转)
- Service Locator Pattern in C#: A Simple Example
- [转]Lazy Initialization and the DAO pattern with Hibernate and Spring
- Lazy Initialization and the DAO pattern with Hibernate and Spring(1)
- Lazy Initialization and the DAO pattern with Hibernate and Spring (2)
- Lazy Initialization and the DAO pattern with Hibernate and Spring (3)
- Using a Service Locator to Work with MessageBoxes in an MVVM Application
- Lazy Initialization and the DAO pattern with Hibernate and Spring
- Lazy Initialization and the DAO pattern with Hibernate and Spring(Spring 与Hibernate的延迟加载和Dao模式)
- Optimizing C# Refactoring Performance with Web Projects in VS 2005
- Servlet.service() for servlet [springServlet] in context with path [] threw exception [Handler proce
- Service Locator Pattern
- service structure flowchart with full stack functionality in a brife map
- 期待已久的一本电子书出来了:Applying Domain-Driven Design and Patterns: With Examples in C# and .NET
- Implementing the Singleton Pattern in C#
- 今天遇到了这样一个问题 Exception in thread "main" org.hibernate.LazyInitializationException: could not initiali
- Java Service Locator Pattern(服务器定位模式)
- Observer Design Pattern in C#!
- Servlet.service() for servlet [springServlet] in context with path [/TESTVIDEO] threw exception [Req
- How to create a DLL library in C and then use it with C#