Route factory which creates instances based on database context and model I am trying to bridge the gap between the database context and routes that are stored in the database.

The factory is designed so that when used in other assemblies, you are forced to use the database context which is known to contain the DbSet which can provide the required data to populate the route.

In the assembly in which the factory resides, you can specify the database context to use so that if more route types are created the route factory can provide different types of route to other classes within the assembly.

However, the idea initially behind the factory was that the assemblies which reference the assembly with the factory could also specify a database context or model as long as it inherits the base database context or model. I'm aware that making the methods internal prevents this, but the methods have been made internal as they may be removed if I refactor the way everything works.

The following is the class:

namespace Sapphire.Cms.Web.Routing
{
    using Sapphire.Cms.Data.Entity;
    using Sapphire.Cms.Models;
    using System;
    using System.Web.Routing;

    public class RouteFactory : IRouteProvider
    {
        public virtual RouteBase GetRoute(IRouteHandler routeHandler)
        {
            DbContextTypeWrapper&lt;SapphireDbContext&lt;SiteTree&gt;, SiteTree&gt; dbContextTypeWrapper = new DbContextTypeWrapper&lt;SapphireDbContext&lt;SiteTree&gt;, SiteTree&gt;();
            return GetRoute(dbContextTypeWrapper, routeHandler);
        }

        internal virtual RouteBase GetRoute(DbContextTypeProvider databaseContextTypeProvider, IRouteHandler routeHandler)
        {
            return GetRoute(databaseContextTypeProvider, typeof(SiteTree), routeHandler);
        }

        internal virtual RouteBase GetRoute(DbContextTypeProvider databaseContextTypeProvider, Type model, IRouteHandler routeHandler)
        {
            Type catchallRoute = typeof(CatchallRoute&lt;,&gt;).MakeGenericType(new Type[] {
                databaseContextTypeProvider.DbContextType,
                model
            });

            Type routeTypeWrapper = typeof(RouteTypeWrapper&lt;&gt;).MakeGenericType(new Type[] {
                catchallRoute
            });

            RouteTypeProvider routeTypeProvider = (RouteTypeProvider)Activator.CreateInstance(routeTypeWrapper);

            return GetRoute(routeTypeProvider, routeHandler);
        }

        private static RouteBase GetRoute(RouteTypeProvider routeTypeProvider, IRouteHandler routeHandler)
        {
            Object[] constructorParameters = new Object[]
            {
                routeHandler
            };

            return (RouteBase)Activator.CreateInstance(routeTypeProvider.RouteType, constructorParameters);
        }

        #region IRouteProvider Members
        RouteBase IRouteProvider.GetRoute(IRouteHandler routeHandler)
        {
            return GetRoute(routeHandler);
        }
        #endregion
    }
}


As you can see the class makes heavy use of reflection, which is bad for performance, however the intended use of this factory is that it should only ever have to get one route, a catchall route.

My questions are:


Based on what was said, should I keep the internal methods internal or make them public?
Should the factory be refactored to improve performance despite the intention being to only ever use it once per request?
Any particular reason you have all those using statements in the namespace itself?



This line:


DbContextTypeWrapper&lt;SapphireDbContext&lt;SiteTree&gt;, SiteTree&gt; dbContextTypeWrapper = new DbContextTypeWrapper&lt;SapphireDbContext&lt;SiteTree&gt;, SiteTree&gt;();



throws a gray-flag for me. Perhaps you should consider injecting the DbContextTypeWrapper into the RouteFactory? It seems to have an awful dependence on certain specifics, that can be abstracted away.

Another suggestion, would be to consider generics for it, considering you also depend on SiteTree as well.

The ideal solution would be an interface ISiteTree that you depend on, regardless of the SiteTree implementation. You could provide a default SiteTree implementation, or allow the additional assemblies to provide their own.

Likewise, the use of internal tends to lend way to some particular properties, for example, the behavior between assemblies can be different. This is particularly foul. You should consider either marking the internal methods public, or marking them private.

Depending on what you have access to, you should consider interfaces/generics again to allow for the DbContextTypeWrapper to vary a little between assemblies. By restricting the public implementation to SapphireDbContext, you also restrict it to only those DB types that SapphireDbContext supports. (If it only supports MSSQL, then you'll need an MSSQL server for each-and-every other project you use this in.)



Though I do not generally advocate the use of var, you could shorten some of your lines with it. (Especially the obscenely long ones.)