Tuesday, February 7, 2012

Joel's DynamicCommandInvoker magic to empower wormholes

using System;

using System.Dynamic;

using System.Diagnostics;

using System.Linq;

using OurApp.Core.Repositories;

using OurApp.Core.Services;

namespace OurApp.Web.UI.CommandProcessing

{

   [DebuggerStepThrough]

   public class DynamicCommandInvoker: DynamicObject, IDynamicCommandInvoker

   {

      private readonly string CommandsNamespace = "";

      

      public DynamicCommandInvoker(string commandNamespace = "")

      {

         this.CommandsNamespace = commandNamespace;

      }

      

      public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args,

            out object result)

      {

         result = default(object);

         

         var processorName = BuildCommandProcessorName(binder.Name);

         var type = Type.GetType(processorName);

         

         
//ensure processor type exists and is present in local assembly

         if (type == null) throw new Exception(string.Format("please make sure your

               command processor class exists and is in the {0} namespace)",

               CommandsNamespace));

         

         var processor = Activator.CreateInstance(type, args);

         

         ResolveDependencies(processor);

         

         
//ensure processor is an ActionCommand

         if (processor == null || !(processor is CommandBase)) throw new Exception("please

               make sure your command processor inherits from ActionCommand");

         

         result = ((CommandBase)processor).Process();

         

         return true;

      }

      

      private void ResolveDependencies(object command)

      {

         var type = command.GetType();

         var props = type.GetProperties(System.Reflection.BindingFlags.Public |

               System.Reflection.BindingFlags.Instance).Where(prop => prop.CanWrite &&

               prop.PropertyType.GetInterfaces().Any(iface => iface == typeof(IRepository) ||

               iface == typeof(IService)));

         props.ForEach(prop =>

            {

               var value = ServiceLocator.Get(prop.PropertyType);

               if (value != null) prop.SetValue(command, value, null);

            });

      }

      

      private string BuildCommandProcessorName(string methodName)

      {

         string formatString = CommandsNamespace + ".{0}Command";

         return string.Format(formatString, methodName);

      }

   }

   

   public interface IDynamicCommandInvoker

   {

   }

}

No comments:

Post a Comment