Category: Uncategorized


Deep Validation with DataAnnotations

August 1st, 2010 — 12:57pm

The following attribute will allow complex child properties to be validated when using the Validator.TryValidateObject in System.ComponentModel.DataAnnotations.

Comment » | Uncategorized

NInject vs. StructureMap vs. I Made This

April 24th, 2009 — 1:10pm

As I’ve mentioned before my team is working on a large scale ASP.NET MVC application and we’re using dependency injection to decouple our data access layer from the application. Initially we were using NInject as our IoC tool of choice. It’s lightweight and has a really nice configuration DSL and it’s pretty fast.

The problem arose when trying to get NInject’s scope caching to work. It has this nifty feature where it will cache the objects it creates and you could specify the scope of that caching…for example SingletonBehavior, or OnPerSessionBehavior. That’s great but I couldn’t make it work, regardless of the configuration it would always return a brand new object every time.

So then I went and checked out StructureMap. It’s a little more complex to get set up and I personally don’t think it’s registration DSL is as nice as NInject’s but it works. It has a similar caching feature where you can specify an Instance Scope of Application, Session, Request, Thread, etc. Same problem though, no matter how I configured it the caching was always at the Application level. So every session in the app would get back the same objects…not very secure on the data front.

Now, I am completely open to the possibility that I don’t know enough about either of these tools and that the roadblocks I ran into were user error. However, I realized I was spending way too much time on something that is essentially a very simple problem. Here’s what I needed out of an IoC tool:

1. Constructor Injection – I don’t really care about property or method injection, just constructors
2. Cache the Output at Session Level
3. Easy Registration with Constructor Args

So the following is what I came up with to solve the problem:

namespace DI {
 
    internal class InjectionBinder {
        public Type Abstract { get; set; }
        public Type Concrete { get; set; }
        public object[] CtorArgs { get; set; }
    }
 
    /// <summary>
    /// A lightweight dependency injection tool that supports constructor injection and HttpContext.Session caching.
    /// </summary>
    public static class Injector {
 
        private const string SessionBindingKey = "__InjectorBindings__";
        private const string SessionCacheKey = "__InjectorCache__";
 
        private static List<InjectionBinder> _bindings {
            get {
                if (HttpContext.Current.Session[SessionBindingKey] == null)
                    HttpContext.Current.Session[SessionBindingKey] = new List<InjectionBinder>();
                return (List<InjectionBinder>)HttpContext.Current.Session[SessionBindingKey];
            }
            set { HttpContext.Current.Session[SessionBindingKey] = value; }
        }
 
        private static List<KeyValuePair<Type, object>> _cache {
            get {
                if (HttpContext.Current.Session[SessionCacheKey] == null)
                    HttpContext.Current.Session[SessionCacheKey] = new List<KeyValuePair<Type, object>>();
                return (List<KeyValuePair<Type, object>>)HttpContext.Current.Session[SessionCacheKey];
            }
            set { HttpContext.Current.Session[SessionCacheKey] = value; }
        }
 
        /// <summary>
        /// Returns a concrete instance of the specified abstract type using the provided bindings and 
        /// attempts to satisfy that type's constructor arguments.
        /// </summary>
        /// <param name="abstractType">The abstract type of the object to initialize.</param>
        /// <returns></returns>
        public static object GetInstance(Type abstractType) {
 
            // Return the item from the cache if it's in there
            var cache = _cache.ToDictionary(o => o.Key, o => o.Value);
            if (cache.ContainsKey(abstractType))
                return cache[abstractType];
 
            // If the type is in the bindings, return the concrete
            var foundBinding = _bindings.Find(b => b.Abstract == abstractType);
            if (foundBinding != null)
                return Activator.CreateInstance(foundBinding.Concrete, foundBinding.CtorArgs);
 
            object obj = null;
            var ctors = abstractType.GetConstructors().ToList();
 
            // If the type has no constructor, then just create one
            if (ctors.Count == 0)
                return Activator.CreateInstance(abstractType);
 
            // If there are constructors, find one which takes arguments of the types we have binders for
            ctors.ForEach(c => {
                var prms = c.GetParameters().ToList();
                var args = new List<object>();
                var haveBindings = true;
                prms.ForEach(p => {
                    var binding = _bindings.Find(b => b.Abstract == p.ParameterType);
                    if (binding == null) { haveBindings = false; }
                    else { args.Add(Activator.CreateInstance(binding.Concrete, binding.CtorArgs)); }
                });
                if (haveBindings) { obj = Activator.CreateInstance(abstractType, args.ToArray()); }
            });
 
            return obj;
        }
 
        /// <summary>
        /// Returns a concrete instance of the specified abstract type using the provided bindings and 
        /// attempts to satisfy that type's constructor arguments.
        /// </summary>
        /// <typeparam name="TAbstract">The abstract type of the object to initialize.</typeparam>
        /// <returns></returns>
        public static TAbstract GetInstance<TAbstract>() where TAbstract : class {
            return GetInstance(typeof (TAbstract)) as TAbstract;
        }
 
        /// <summary>
        /// Creates a binding rule between an abstract type and a concrete type.
        /// </summary>
        /// <typeparam name="TAbstract">The abstract type for the binding.</typeparam>
        /// <typeparam name="TConcrete">The concrete type for the binding</typeparam>
        /// <param name="ctorArgs">The list of constructor arguments to use when initializing the instance of the concrete type.</param>
        public static void Bind<TAbstract, TConcrete>(object[] ctorArgs) {
            var binding = _bindings.Find(b => b.Abstract == typeof(TAbstract));
            if (binding != null) {
                binding.Concrete = typeof(TConcrete);
                binding.CtorArgs = ctorArgs;
            } else {
                _bindings.Add(new InjectionBinder {
                    Abstract = typeof(TAbstract),
                    Concrete = typeof(TConcrete),
                    CtorArgs = ctorArgs
                });
            }
        }
 
        /// <summary>
        /// Clears all Injector binding rules and empties the internal cache.
        /// </summary>
        public static void Kill() {
            HttpContext.Current.Session[SessionBindingKey] = null;
            HttpContext.Current.Session[SessionCacheKey] = null;
        }
    }
}

And here’s how we register the bindings:

private static void BindInjectionContainer() {
    Injector.Kill(); // Clears out previously created bindings and empties the cache
 
    var currentClient = new Client(); // Doesn't matter...just an example
    var currentUser = new User();
    var currentCulture = "en-US";
 
    Injector.Bind<IClientRepository, ClientRepository>(new object[] { currentClient, currentCulture });
    Injector.Bind<IUserRepository, UserRepository>(new object[] { currentClient, currentCulture, currentUser });
    Injector.Bind<ISecurityRepository, SecurityRepository>(new object[] {});
}

And lastly, here’s how you request an object:

var secRepo = Injector.GetInstance<ISecurityRepository>();

So, it may be ridiculous to roll-your-own on the IoC container but as you can see it was pretty simple to get what I needed. It’s very solution specific but what’s wrong with that. In this instance it’s pretty easy to swap out for something more feature rich if necessary but for now…I call YAGNI on all that.

3 comments » | Uncategorized

StackOverflow Love

December 17th, 2008 — 1:31pm

I love stackoverflow.com!  It doesn't get much better than a bunch of geeks answering each others' questions for merit badges ;)

Comment » | Uncategorized

Echo-ORM

October 30th, 2008 — 12:48pm

I think we've all encountered the fear of open source software amongst some of our clients.  I like to call it ossphobia.  It basically amounts to a categorical rejection of anything that doesn't arrive in shrink wrap with a shiny holographic label displaying a Microsoft logo.  While I am primarily a Microsoft developer, I am by no means a fanatic and often find that the best solution to a problem is exactly the opposite of the solution championed by Microsoft.

Recently I was working with one such ossphobic client on a reletively simple reporting application.  We were in need of a very simple ORM-lite solution (similar to what SubSonic provides) to store meta-data information in a database.  My first thought was, "Well, why don't we just use SubSonic?"  This was met with blank stares and a palatable sense of "Oh no he didn't." hanging in the air.  So, after realizing that my chances of changing this client's mind on the subject of OSS was nigh impossible, I decided, "The hell with it, if they don't want to use the inexpensive solution, I'll just write my own ORM and call it custom software."

Some of you (whoever you are) will find the idea of rolling your own ORM in the age of NHibernate, LINQ to SQL, SubSonic, and etc. ridiculous.  "There are so many good frameworks out there, why would you ever want to write your own?"  Well, I'll give you a few reasons…you may not like them…but I do so you'll just have to deal.

  1. Full Control – One of the things that's great about SubSonic for example is that it just flat works out of the box.  You do some simple configuration, generate your objects, and your off and running.  Literally, 10 minutes.  The problem here is that much of the internals of SubSonic are kind of a black box.  The source code, while well written, can still be a pretty deep stack.  If I for example wanted to add a feature to SubSonic, I'd find the learning curve pretty high.  A custom ORM designed specifically for simplicity offers a much lower barrier to extension.
  2. The Right Tool for the Job – So in the specific case that prompted me to write my own framework, there were some specific features that we needed.  I was able to winnow down my concept to cover just what was needed at the time (the YAGNI principle).  This allowed my framework to be really targeted and the API that I exposed to consumers of the framework was extremely simple.  
  3. I Like Learning – I don't often get the chance to work on framework type projects so this gave me the opportunity to really try out some ideas in an environment that wasn't tied immediately to a project deliverable.  I think everyone should have a side project that takes them outside the path of their normal daily development…I have several such side endeavors.

So, now that all that's been said.  I'm introducing Echo ORM as an open source project on Google Code.  It's a very small framework and in a very alpha state, but I'd love some feedback on the approach that I've taken and I welcome comments or contributions.

Echo ORM: http://code.google.com/p/echo-orm

Comment » | Uncategorized

Excellent Post on Project Size

October 21st, 2008 — 3:09pm

An excellent post on project size…as in how many people are on a project.

http://semanticvector.blogspot.com/2008/10/more-programmers-more-code.html

Personally, I've always subscribed to the Amazon two pizza maxim.  Any project team should be able to eat comfortably on two large pizzas.  As soon as someone says, "Say, I think we might need to order a third pie."  You know your project is too big and is likely going to suffer from hauling around the extra weight.

Comment » | Uncategorized

Wi-Fi Mile High

October 5th, 2008 — 10:22pm

So, I’m on a plane right now and there are at least five people in my immediate vicinity working on laptops. Every single one of these people is reading email in Outlook. The obvious disgust at Outlook aside, this leads me to the question, “Why don’t we have Wi-Fi on every commercial flight yet?”.

I myself would be incredibly attracted to any airline that offered this service. It wouldn’t even have to be free. I’d happily pay an extra $10 for my ticket if it came with even modestly quick Internet access.

I doubt if any airline execs read this particular blog, but if you are…Wi-Fi…all I have to say…Wi-Fi.

Comment » | Uncategorized

Back to top