/// <summary>
 /// Maps the domain routes to the given domain controller.
 /// </summary>
 /// <typeparam name="TController">The domain controller.</typeparam>
 /// <param name="config">The <see cref="HttpConfiguration"/> instance.</param>
 /// <param name="routeName">The name of the route.</param>
 /// <param name="routePrefix">The prefix of the route.</param>
 /// <param name="batchHandler">The handler for batch requests.</param>
 /// <returns>The task object containing the resulted <see cref="ODataRoute"/> instance.</returns>
 public static async Task <ODataRoute> MapODataDomainRoute <TController>(
     this HttpConfiguration config,
     string routeName,
     string routePrefix,
     ODataDomainBatchHandler batchHandler = null)
     where TController : ODataDomainController, new()
 {
     return(await MapODataDomainRoute <TController>(
                config, routeName, routePrefix, () => new TController().Domain, batchHandler));
 }
        /// TODO GitHubIssue#51 : Support model lazy loading
        /// <summary>
        /// Maps the domain routes to the given domain controller.
        /// </summary>
        /// <typeparam name="TController">The domain controller.</typeparam>
        /// <param name="config">The <see cref="HttpConfiguration"/> instance.</param>
        /// <param name="routeName">The name of the route.</param>
        /// <param name="routePrefix">The prefix of the route.</param>
        /// <param name="domainFactory">The callback to create domain instances.</param>
        /// <param name="batchHandler">The handler for batch requests.</param>
        /// <returns>The task object containing the resulted <see cref="ODataRoute"/> instance.</returns>
        public static async Task <ODataRoute> MapODataDomainRoute <TController>(
            this HttpConfiguration config,
            string routeName,
            string routePrefix,
            Func <IDomain> domainFactory,
            ODataDomainBatchHandler batchHandler = null)
            where TController : ODataDomainController, new()
        {
            Ensure.NotNull(domainFactory, "domainFactory");

            using (var domain = domainFactory())
            {
                var model = await domain.GetModelAsync();

                model.EnsurePayloadValueConverter();
                var conventions = CreateODataDomainRoutingConventions <TController>(config, model);

                if (batchHandler != null && batchHandler.DomainFactory == null)
                {
                    batchHandler.DomainFactory = domainFactory;
                }

                var routes = config.Routes;
                routePrefix = RemoveTrailingSlash(routePrefix);

                if (batchHandler != null)
                {
                    batchHandler.ODataRouteName = routeName;
                    var batchTemplate = string.IsNullOrEmpty(routePrefix) ? ODataRouteConstants.Batch
                        : routePrefix + '/' + ODataRouteConstants.Batch;
                    routes.MapHttpBatchRoute(routeName + "Batch", batchTemplate, batchHandler);
                }

                DefaultODataPathHandler odataPathHandler = new DefaultODataPathHandler();

                var getResolverSettings = typeof(WebApiODataEx.HttpConfigurationExtensions)
                                          .GetMethod("GetResolverSettings", BindingFlags.NonPublic | BindingFlags.Static);

                if (getResolverSettings != null)
                {
                    var          resolveSettings = getResolverSettings.Invoke(null, new object[] { config });
                    PropertyInfo prop            = odataPathHandler
                                                   .GetType().GetProperty("ResolverSetttings", BindingFlags.NonPublic | BindingFlags.Instance);

                    if (null != prop && prop.CanWrite)
                    {
                        prop.SetValue(odataPathHandler, resolveSettings, null);
                    }

                    // In case WebAPI OData fix "ResolverSetttings" to "ResolverSettings".
                    // So we set both "ResolverSetttings" and "ResolverSettings".
                    prop = odataPathHandler
                           .GetType().GetProperty("ResolverSettings", BindingFlags.NonPublic | BindingFlags.Instance);
                    if (null != prop && prop.CanWrite)
                    {
                        prop.SetValue(odataPathHandler, resolveSettings, null);
                    }
                }

                var routeConstraint =
                    new DefaultODataPathRouteConstraint(odataPathHandler, model, routeName, conventions);
                var route = new ODataRoute(routePrefix, routeConstraint);
                routes.Add(routeName, route);
                return(route);
            }
        }