Skip to content

Instantly share code, notes, and snippets.

@mkmurray
Created February 27, 2013 15:49
Show Gist options
  • Save mkmurray/5048903 to your computer and use it in GitHub Desktop.
Save mkmurray/5048903 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using FubuCore;
using FubuCore.CommandLine;
using FubuCore.Util;
using StructureMap;
using log4net;
namespace Recapitulator.Common
{
public class StructureMapCommandFactory : ICommandFactory
{
private readonly Cache<string, Type> _commandTypes = new Cache<string, Type>();
private readonly IContainer _container;
private readonly CommandFactory _factory;
private readonly ILog _logger = LogManager.GetLogger(typeof(StructureMapCommandFactory));
public StructureMapCommandFactory(IContainer container)
{
_container = container;
_factory = new CommandFactory();
}
public CommandRun BuildRun(string commandLine)
{
var args = StringTokenizer.Tokenize(commandLine);
return BuildRun(args);
}
public CommandRun BuildRun(IEnumerable<string> args)
{
if (!args.Any())
return _factory.HelpRun(new Queue<string>());
var queue = new Queue<string>(args);
var commandName = queue.Dequeue().ToLowerInvariant();
switch (commandName)
{
case "?":
case "help":
return _factory.HelpRun(queue);
default:
return _commandTypes.Has(commandName) ? CreateRun(queue, commandName) : _factory.InvalidCommandRun(commandName);
}
}
public void RegisterCommands(Assembly assembly)
{
_container.Configure(c => assembly
.GetExportedTypes()
.Where(x => x.Closes(typeof(FubuCommand<>)) && x.IsConcrete())
.Each(t =>
{
c.For(typeof(IFubuCommand)).Add(t).Named(CommandFactory.CommandNameFor(t));
_commandTypes[CommandFactory.CommandNameFor(t)] = t;
}));
_factory.RegisterCommands(assembly);
}
public IFubuCommand Resolve(string commandName)
{
return _container.TryGetInstance<IFubuCommand>(commandName);
}
private CommandRun CreateRun(Queue<string> queue, string commandName)
{
try
{
ScanCommandAssembly(commandName);
var command = Resolve(commandName);
var usageGraph = new UsageGraph(_commandTypes[commandName]);
var input = usageGraph.BuildInput(queue);
return new CommandRun
{
Command = command,
Input = input
};
}
catch (InvalidUsageException ex)
{
_logger.Error("Invalid usage", ex);
}
catch (Exception ex)
{
_logger.Error("Error parsing input", ex);
}
return _factory.HelpRun(commandName);
}
private void ScanCommandAssembly(string commandName)
{
var type = _commandTypes[commandName];
_container.Configure(c => c.Scan(s =>
{
s.Assembly(type.Assembly);
s.LookForRegistries();
}));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment