Search code examples
wcfdependency-injectionautofacself-hostingservicehost

WCF - How to pass service class constructor parameter when initializing Service Host(TypeOf(Service-Class))


I have WCF service class 'MusicServiceManager' with the constructor that takes the parameter of IAppAmbientState. I need to pass parameter value to MusicServiceManager constructor at time initializing Service Host. I don't want singleton implementation for IAppAmbientState.

Service Contract

[ServiceContract]
public interface IAlbumService
{
    [OperationContract]
    string TestMessage();

    [OperationContract]
    IEnumerable<AlbumData> GetAlbums();

    [OperationContract(Name = "GetAlbumByID")]
    AlbumData GetAlbum(Guid ID);

    [OperationContract(Name = "GetAlbumByName")]
    AlbumData GetAlbum(string name);
}

AppAmbientState

public class AppAmbientState : IAppAmbientState
{
    public IContainer ServiceContainer { get; }

    public AppAmbientState(
        IContainer container  // autofac DIC container
        )
    {
        ServiceContainer = container;
    }
}

MusicServiceManager

public class MusicServicesManager : IAlbumService
{
    private readonly IAppAmbientState _appAmbientState;
   
    public MusicServicesManager(IAppAmbientState appAmbientState)
    {
        this._appAmbientState= appAmbientState;         
    }

    public AlbumData GetAlbum(Guid ID)
    {
        throw new NotImplementedException();
    }

Service Host Configuration Class

public class ServiceHostConfiguration : IServiceHostConfiguration
{
    private readonly ServiceHost hostMusicServiceManager;

    public ServiceHostConfiguration()
    {
        var container = ContainerConfiguration.Configure();

        AppAmbientState AppAmbientStateInstance = new AppAmbientState(container);
        // need help here... MusicServiceManager(AppAmbientStateInstance)???? 
        // ideally I don't want to define my base address in class

        this.hostMusicServiceManager = new ServiceHost(typeof(MusicServicesManager));
    }

    public void InitializeService()
    {
        try
        {
            this.hostMusicServiceManager.Open();
            Console.WriteLine("App Web Services Started. Press [Enter] To Exit  ");
        }
        catch(Exception exp)
        {
            Console.WriteLine("App Web Services Could Not Start::  ", exp);
        }
        
    }

    public void CloseService()
    {
        this.hostMusicServiceManager.Close();
    }
}

Autofac DI Container

public static class ContainerConfiguration
{
    public static IContainer Configure()
    {
        var builder = new ContainerBuilder();
        
        //Application Configuration
        builder.RegisterType<Application>().As<IApplication>();
        builder.RegisterType<ServiceHostConfiguration>().As<IServiceHostConfiguration>();
        builder.RegisterType<AppAmbientState>().As<IAppAmbientState>();
        builder.RegisterType<MusicServicesManager>().As<IAlbumService>();

Solution

  • Here is my Demo:

    This is the project directory:

    enter image description here

    Program.cs:

    using Autofac;
    using Autofac.Integration.Wcf;
    using System;
    using System.ServiceModel;
    using System.ServiceModel.Description;
    
    namespace AutofacTest
    {
        class Program
        {
            static void Main(string[] args)
            {
                ContainerBuilder builder = new ContainerBuilder();
                builder.RegisterType<Logger>().As<ILogger>();
                builder.RegisterType<Service>();
    
                using (IContainer container = builder.Build())
                {
                    
                    ServiceHost host = new ServiceHost(typeof(Service));
                    host.AddDependencyInjectionBehavior<Service>(container);
                    host.Open();
                    Console.WriteLine("The host has been opened.");
                    Console.ReadLine();
                    host.Close();
                  
                }
            }
        }
        [ServiceContract]
        public interface IService
        {
            [OperationContract]
            string Test();
        }
    
        public interface ILogger
        {
        }
    
        public class Service : IService
        {
            private readonly ILogger logger;
    
            
            public Service(ILogger logger)
            {
                this.logger = logger;
            }
    
            public string Test()
            {
                return "TEst1";
            }
        }
    
        public class Logger : ILogger
        {
    
        }
    }
    

    App.config:

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
        <startup> 
            <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
        </startup>
        <system.serviceModel>
            <services>
                <service name="AutofacTest.Service">
                    <endpoint address="" binding="basicHttpBinding" contract="AutofacTest.IService" name="TestServiceEndPoint" />
                    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" name="TestServiceMexEndPoint" />
                    <host>
                        <baseAddresses>
                            <add baseAddress="http://localhost/TestService" />
                        </baseAddresses>
                    </host>
                </service>
            </services>
            <behaviors>
                <serviceBehaviors>
                    <behavior>
                        <serviceDebug includeExceptionDetailInFaults="true" />
                        <serviceMetadata httpGetEnabled="true" />
                    </behavior>
                </serviceBehaviors>
            </behaviors>
        </system.serviceModel>
      <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
          <dependentAssembly>
            <assemblyIdentity name="Autofac" publicKeyToken="17863af14b0044da" culture="neutral" />
            <bindingRedirect oldVersion="0.0.0.0-5.2.0.0" newVersion="5.2.0.0" />
          </dependentAssembly>
        </assemblyBinding>
      </runtime>
    </configuration>
    

    Feel free to let me know if the problem persists.