PBMining

Searching...
Friday, August 10, 2012

Exploring MVC framework in deep - DependencyResolver Class

9:55 PM

DependencyResolver is project wide dependency resolver class in MVC framework. It is used to resolve the instance of particular type and also provide the customization to set custom dependency resolver to resolve the instance.

In three way you can customize resolver for resolve the instance of any type.first you can pass the instance of IDependencyResolver or you can specified common service locator that can resolve one or all instances or you can provide both services individually to resolve the instance of given type. if no customization is made then DefaultDependencyResolver is used to create the instance using System.Activator.

First method has simple definition it just set CustomDependencyResolver as a current resolver.



 private IDependencyResolver _current = new DefaultDependencyResolver();

 public void InnerSetResolver(IDependencyResolver resolver) {
            if (resolver == null) {
                throw new ArgumentNullException("resolver");
            }
            _current = resolver;
        }

Second method perform some extra work to create service. It first search for two public methods GetInstance and GetAllInstances in service locator using GetMethod method of Type class and check for some criteria that above method should matched

        public void InnerSetResolver(object commonServiceLocator) {
            if (commonServiceLocator == null) {
                throw new ArgumentNullException("commonServiceLocator");
            }

            Type locatorType = commonServiceLocator.GetType();
            MethodInfo getInstance = locatorType.GetMethod("GetInstance", new[] { typeof(Type) });
            MethodInfo getInstances = locatorType.GetMethod("GetAllInstances", new[] { typeof(Type) });

            if (getInstance == null || getInstance.ReturnType != typeof(object) ||
            getInstances == null || getInstances.ReturnType != typeof(IEnumerable<object>)) {
                        throw new ArgumentException(String.Format(CultureInfo.CurrentCulture,
                        MvcResources.DependencyResolver_DoesNotImplementICommonServiceLocator,
                        locatorType.FullName
                    ),
                    "commonServiceLocator"
                );
            }
       var getService = (Func<Type, object>)Delegate.CreateDelegate(typeof(Func<Type, object>), commonServiceLocator, getInstance);
       var getServices = (Func<Type, IEnumerable<object>>)Delegate.CreateDelegate(typeof(Func<Type, IEnumerable<object>>), commonServiceLocator, getInstances);

             _current = new DelegateBasedDependencyResolver(getService, getServices);
        }
        

This method creates delegate to both methods and passed it to constructor of DelegateBasedDependencyResolver so it can call these method to resolve the instance of particular type.

        [SuppressMessage("Microsoft.Design", "CA1006:DoNotNestGenericTypesInMemberSignatures",
        Justification = "This is an appropriate nesting of generic types.")]
        public void InnerSetResolver(Func<Type, object> getService, Func<Type, IEnumerable<object>> getServices) {
            if (getService == null) {
                throw new ArgumentNullException("getService");
            }
            if (getServices == null) {
                throw new ArgumentNullException("getServices");
            }

            _current = new DelegateBasedDependencyResolver(getService, getServices);
        }

Both above method create a delegate based service using DelegateBasedDependencyResolver class.See below implementation of DelegateBasedDependencyResolver class.

        private class DelegateBasedDependencyResolver : IDependencyResolver {
                 Func<Type, object> _getService;
                 Func<Type, IEnumerable<object>> _getServices;

                 public DelegateBasedDependencyResolver(Func<Type, object> getService, Func<Type, IEnumerable<object>> getServices) {
                     _getService = getService;
                     _getServices = getServices;
                 }
                 [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "This method might throw exceptions whose type we cannot strongly link against; namely, ActivationException from common service locator")]
                 public object GetService(Type type) {
                     try {
                         return _getService.Invoke(type);
                     }
                     catch {
                         return null;
                     }
                 }

                 public IEnumerable<object> GetServices(Type type) {
                     return _getServices(type);
                 }
             }

    

You can see here when we request for single or multiple instances of any type it just invoked appropriate delegate to resolve the instance.

as i mention above if no customization is provided then DefaultDependencyResolver use to serve the request for particular type. see the below implementation.

    private class DefaultDependencyResolver : IDependencyResolver {
            [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes",
             Justification = "This method might throw exceptions whose type we cannot strongly link against; namely,
             ActivationException from common service locator")]

            public object GetService(Type serviceType) {
                try {
                    return Activator.CreateInstance(serviceType);
                }
                catch {
                    return null;
                }
            }

            public IEnumerable<object> GetServices(Type serviceType) {
                return Enumerable.Empty<object>();
            }
        }

You can see here it just a simple implementation.When you request for an instance of any type it use System.Activator class to create an instance. You can see that this class is only able to resolve single instance of any given type.Method for retrieve multiple instance is not implementedin this class.

There are some properties define in this class that is not included in above codes so its better you download source of MVC framework for better understanding. please share this post if you get anything useful.

0 comments:

Post a Comment

Write your review about this post.