SimpleInjector WCF Extension and Web service hosted in a Windows Service

Apr 3, 2013 at 2:41 PM
Edited Apr 3, 2013 at 2:42 PM
Hi

I use my own framework to host each web service in a thread which is started when I start a windows service, in other words I have hosted the web service using a windows service. In the starting process of my windows service I intialize simpleInjector container and register my services and the respective Implementation. I am also using he SimpleInjector WCF integration . In the boot process i have done the following

SimpleInjectorServiceHostFactory.SetContainer(_container);

Next when each of my WCF service is hosted in the Windows Service I created a ServiceHost by calling the following

new SimpleInjectorServiceHost(container, type, new Uri[0])

When the above statement is executed the following exception is thrown

"The service type provided could not be loaded as a service because it does not have a default (parameter-less) constructor. To fix the problem, add a default constructor to the type, or pass an instance of the type to the host"

My Questions is why does SimpleInjectorServiceHost requires to have the WCF service with paramterless constructor ? I have already given the container to the SimpleInjectorServiceHost which should resolve the dependencies needed by the Consgtructor of my WCF service .

I cannot have a default constructor to my service.
Coordinator
Apr 3, 2013 at 8:21 PM
Edited Apr 3, 2013 at 8:22 PM
That exception is not thrown by Simple Injector. The SimpleInjectorServiceHost (of course) allows injecting dependencies into non-default constructors. Can you post more code that exactly shows how you create and use the SimpleInjectorServiceHost?
Apr 4, 2013 at 5:43 AM
Hi

Here is some more code and explanation

Boot Strapping IOC

private void BootStrapIOCServiceProvider()
    {

        if (_container == null)
        {
            _container = new SimpleInjector.Container();
            SimpleInjectorServiceHostFactory.SetContainer(_container);
            RegisterTypesInContainer();
        }

    }
WCF Base class which creates the service host for each service
This is called when each thread is created by by windows service

public class WCFServiceBase<T> : ServiceBase
{
    protected  ServiceHostBase ServiceHost;
    protected IServiceLocator _serviceLocator;

    protected WCFServiceBase(ManualResetEvent threadCancel, ManualResetEvent threadCancelled, IServiceLocator serviceLocator)
        : base(threadCancel, threadCancelled,serviceLocator)
    {
        _serviceLocator=serviceLocator;
    }


    protected override void Initialize()
    {
        base.Initialize();
        Open();
    }

    protected override void Terminate()
    {
        Close();
        base.Terminate();
    }

    protected void Close()
    {
        try
        {
            ServiceHost.Close();
        }
        catch (Exception)
        {
            ServiceHost.Abort();
        }
    }

    protected void Open()
    {
        ServiceHost = CreateServiceHostBase();
        ServiceHost.Open();
    }

    protected override void Process()
    {
        while (!ThreadCancel.WaitOne(1000))
        {
        }
    }

    protected ServiceHostBase CreateServiceHostBase()
    {
        var type  =  TypeFinder.GetImplementation(T)  // Bad code refactor this 


        return new SimpleInjectorServiceHost(container, type, new Uri[0]);

    }
I hope this helps

I am not sure at this moment if I am missing something . DO I need to use the container. RegiterWCFServcies?

I am looking to find a way to host this WCF services using Simple injector WCF Integration utility hosting them in windows service.

In my earlier project I was using the exact same thing using Windsor code I moved to SimpleInjector because it is much faster than other DI containers

return new DefaultServiceHostFactory()
.CreateServiceHost(typeof(T) .AssemblyQualifiedName, new Uri[0]);


Thanks
Amol
Coordinator
Apr 4, 2013 at 9:04 AM
Hi Amol,

I can't say what exactly is the problem in your case, but here is a working example. Perhaps it helps you to find out why it isn't working in your case. If you found out, please let us know. This might help future users as well:
using System;
using System.Reflection;
using System.ServiceModel;
using System.ServiceModel.Description;

using SimpleInjector;
using SimpleInjector.Integration.Wcf;

public interface ILogger
{
    void Log(string message);
}

public class ConsoleLogger : ILogger
{
    public void Log(string message)
    {
        System.Console.WriteLine(message);
    }
}

[ServiceContract]
public interface IProductService
{
    [OperationContract]
    void DoStuf(string message);
}

public class ProductService : IProductService
{
    ILogger logger;

    public ProductService(ILogger logger)
    {
        Console.WriteLine("Constructor called.");
        this.logger = logger;
    }

    public void DoStuf(string message)
    {
        this.logger.Log(message);
    }
}

class Program
{
    static void Main(string[] args)
    {
        Uri baseAddress = new Uri("http://localhost:8080/ProductService/");

        var container = Bootstrap();
            
        using (ServiceHost host = new SimpleInjectorServiceHost(
            container, typeof(ProductService), baseAddress))
        {
            ServiceEndpoint productEndpoint =
                host.AddServiceEndpoint(typeof(IProductService),
                new WSHttpBinding(), "ProductService");

            host.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true });

            host.AddServiceEndpoint(typeof(IMetadataExchange),
                MetadataExchangeBindings.CreateMexHttpBinding(),
                "http://localhost:8080/ProductService/mex");

            host.Open();

            Console.WriteLine("The Product service is running and is listening on:");
            Console.WriteLine("{0} ({1})", productEndpoint.Address.ToString(), productEndpoint.Binding.Name);
            Console.WriteLine("\nPress any key to stop the service.");
            Console.ReadKey();
        }
    }

    public static Container Bootstrap()
    {
        // Did you know the container can diagnose your configuration? Go to: http://bit.ly/YE8OJj.
        var container = new Container();

        container.EnablePerWcfOperationLifestyle();

        container.RegisterSingle<ILogger, ConsoleLogger>();

        container.RegisterWcfServices(Assembly.GetExecutingAssembly());

        container.Verify();

        return container;
    }
}
I am not sure at this moment if I am missing something . DO I need to use the container. RegiterWCFServcies?
Strictly spoken, you don't need to call the RegisterWcfServices extension method. WCF services are concrete types and the container will be able to create them for you when they're not explicitly registered. Calling that method however does has a clear benefit. By explicitly registering all WCF services in the container, you allow the container to check whether those types (and its dependencies) are configured correctly when calling container.Verify(). In other words, calling RegisterWcfServices is important if you want your DI configuration to be verifiable. Further more, it allows the Diagnostic Services to analyze those types and warn you about any possible misconfiguration.

As a side note, take a look at this article about writing highly maintainable WCF services. It might be applicable to your project.
Marked as answer by dot_NET_Junkie on 11/5/2013 at 7:38 AM
Apr 4, 2013 at 11:09 AM
Thanks

I got it working for me . For some reason it was not working becuase my service was decorated with

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]

I added this programatically now and it is working

Appreciate your help

Thanks
Amol