ServiceStack in a Console Application
4 min read

ServiceStack in a Console Application

I absolutely love ServiceStack. Let’s get that out into the open. With every new project I begin, my first question is “How can I use ServiceStack here?”

My typical reasoning for using ServiceStack is to utilize its amazing web service framework. I could extoll its message-based design and extensibility for pages upon pages.

When I’m working on an ASP.NET MVC web application, I still pull in ServiceStack to get its additional MVC features. This allows me to use the built-in ServiceStack components (e.g., Session, Caching, Authentication, etc.) on top of my favorite web application framework.

However, due to the nature of my job, I am working on console applications that must be run from the Windows Task Scheduler with some regularity. While ServiceStack hooks nicely into the HTTP-based frameworks of web services and web applications, there doesn’t appear to be much utility for it within a pure console application.

This is mostly true if you think of ServiceStack as just a web framework. I personally like to think of ServiceStack as both a web framework and a collection of tools that I think I would build in another life. These tools include the built-in Funq IoC container and the AppSettings abstraction. Examples below on how I’m doing this with a real project.

Using Funq

Funq is ServiceStack’s built-in IoC container. Other amazing IoC containers exist (I personally love Autofac, but I like that this one is built in.

In a typical web application, the Funq container is created correctly at each scope and managed by ServiceStack. In a console application, this level of integration doesn’t work, so instead I hack around it by creating a static container that is available to the entire application. This smells like the Service Locator pattern, but we don’t go down that route by convention. Note that there is nothing technically from stopping a developer from calling the container directly rather than utilizing constructor injection, but we yell at developers who do this.

The code below shows a sample console application that has a static Container that is utilized by the DependencyConfig class. From there, each implementation of an interface utilizes constructor injection to get the implementation of the dependencies.

Program Setup

The following code sample is the main entrypoint of a sample console application. You’ll see that it contains the static readonly Container instance, which DependencyConfig.Setup() actually updates (seen later).

You then can see how the Container is accessed when instantiating a new Worker instance. This is the only use-case of accessing the Container directly from code (similar to the Service Locator pattern).

namespace ServiceStack.Console
{
    static class Program
    {
        public static readonly Container Container = new Container();

        static void Main(string[] args)
        {
            DependencyConfig.Setup();
            new LogConfig(Container.Resolve<IAppSettings>()).Setup();

            var worker = new Worker(Container.Resolve<IWorkManager>());
            worker.Work();
        }
    }
}

Dependency Setup

Utilizing ServiceStack’s specific flavor of Funq, you’ll see that I use the Container.RegisterAutoWiredAs<T, TAs> extension method. This is shorthand for the Container.Register<T>(...) methods, allowing this dependency container setup to be straightforward and easy to update.

namespace ServiceStack.Console
{
    public static class DependencyConfig
    {
        public static void Setup()
        {
            Program.Container.Register<IAppSettings>(x => new AppSettings());
            Program.Container.Register<IDbConnectionFactory>(x =>
            {
                var settings = x.Resolve<IAppSettings>();
                var connectionString = settings.Get("ConnectionString", "default");
                var provider = new OracleOrmLiteDialectProvider();
                var dbFactory = new OrmLiteConnectionFactory(connectionString, provider);
                return dbFactory;
            });

            Program.Container.RegisterAutoWiredAs<WorkRepository, IWorkRepository>();
            Program.Container.RegisterAutoWiredAs<WorkManager, IWorkManager>();
        }
    }
}

The Worker

This is a very simple class that has a constructor-injected dependency of IWorkManager (which is resolved from the Program class above).

namespace ServiceStack.Console
{
    public class Worker
    {
        private readonly IWorkManager manager;

        public Worker(IWorkManager manager)
        {
            this.manager = manager;
        }

        public void Work()
        {
            this.manager.DoWork();
        }
    }
}

Work Manager

The code below contains the interface IWorkManager, and then a concrete implementation of the interface in WorkManager. The WorkManager implementation contains another constructor-injected dependency inIWorkRepository. This dependency is resolved via Program-level Container object during the resolution of the IWorkManager initially.

namespace ServiceStack.Console.Interfaces
{
    public interface IWorkManager
    {
        void DoWork();
    }

    public class WorkManager : IWorkManager
    {
        private readonly IWorkRepository repository;

        public WorkManager(IWorkRepository repository)
        {
            this.repository = repository;
        }

        public void DoWork()
        {
            var data = this.repository.GetData();
            DoTheThing(data);
        }

        private void DoTheThing(object data)
        {
            // Data
        }
    }
}

Work Repository

The IWorkRepository interface below merely returns data from the GetData() method. The concrete implementation, WorkRepository, utilizes ServiceStack’s IDbConnectionFactory interface to inject data access dependencies without needing to know where it’s connecting. This is especially useful when testing data access, as it is trivial to mock out with a database like Sqlite.

namespace ServiceStack.Console.Interface
{
    public interface IWorkRepository
    {
        object GetData();
    }

    public class WorkRepository : IWorkRepository
    {
        private readonly IAppSettings settings;
        private readonly IDbConnectionFactory connectionFactory;

        public WorkRepository(IAppSettings settings, IDbConnectionFactory connectionFactory)
        {
            this.settings = settings;
            this.connectionFactory = connectionFactory;
        }

        public object GetData()
        {
            using (var connection = this.connectionFactory.OpenDbConnection())
            {
                // Get and return data
            }
        }
    }
}

This type of application architecture assures a straightforward unit test plan, as each concrete implementation can be tested in isolation by utilizing mock objects (I like to use Moq for this).

AppSettings Abstraction

I have personally written a strongly-typed configuration abstraction to mirror what is in my web.config or app.config at least a dozen times. I am done with writing that type of tight coupling, as it makes updates a bit too cumbersome.

As a replacement, I now keep a class with the <appSettings /> keys defined, as well as a class with the default values for each of those keys.

namespace ServiceStack.Console
{
    public static class ConfigKeys
    {
        public static readonly string ApiKey = nameof(ApiKey);
        public static readonly string ApplicationName = nameof(ApplicationName);
        public static readonly string ApplicationVersion = nameof(ApplicationVersion);
        public static readonly string Environment = nameof(Environment);
    }

    public static class ConfigValues
    {
        public static readonly string DefaultApiKey = "abcd1234";
        public static readonly string DefaultApplicationName = "ServiceStack Console Test Application";
        public static readonly string DefaultApplicationVersion = "1.0.0";
        public static readonly string DefaultEnvironment = "Local";
    }
}

Using constructor injection and Funq from above, I then pull the data out of the IAppSettings instance by using its IAppSettings.Get<T>(string name, T defaultValue) method. A good example of this is when I retrieve the "ConnectionString" value in the DependencyConfig class above.

Wrapping It All Up

Nothing I typed above is dependent on ServiceStack. I can pull in Autofac and use any of the myriad of web.config or app.config abstraction libraries (or roll my own), and the code will work precisely the same. However, due to my experience level with ServiceStack (and its ease of use, if we’re being honest), I tend to use what I know. In this case, it means pulling in a web framework to utilize its IoC container and application configuration abstraction.