May 28 2010

Resolving assembly bind failures on a server

Category: .NetRory Primrose @ 06:59

Sometimes things just don’t go to plan went you deploy your software to a server. Unfortunately servers don’t come with all your dev tooling so it can be hard to figure out what is going wrong when provided some cryptic exception message.

My current issue is testing deployment of a 4.0 framework built WCF service to a newly provisioned Windows Server 2008 R2 machine. I get the classic WCF error message saying that the service type could not be found for the endpoint. It doesn’t tell me why and I know the service assemblies are in place. Given prior experience I am guessing that the most likely cause is that other dependencies of my service assemblies are not on the machine.

I look to FUSLOGVW.exe to find out these answers. The issue is that this great utility is not on the server image as it comes out of the .Net SDK. With a bit of trickery, it can be used on a server. These are the steps to get this done.

  1. Copy FUSLOGVW.exe from your dev machine to the server (found somewhere around C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin)
  2. Run cmd.exe with elevated privileges to execute reg add HKLM\Software\Microsoft\Fusion /v EnableLog /t REG_DWORD /d 1
    (Kudos to Bart for this one)
  3. Create a logs directory (I tend to use C:\Temp\Logs)
  4. Run FUSLOGVW.exe with elevated privileges
  5. Click Settings 
    • Select Log bind failures to disk
    • Select Enable custom log path
    • Enter the path defined in #3.
      • NOTE: Do not include the trailing \
      • NOTE: The directory must be created first
    • Click OK
  6. Run your application (refresh the browser on the service endpoint in my case)
  7. Click Refresh

Hopefully you will now have some information to work with.

Double clicking on the binding failure gives you all the information about what .Net did to try to find the assembly. The entry in my scenario looks like this:

*** Assembly Binder Log Entry  (28/05/2010 @ 11:35:47 AM) ***

The operation failed.
Bind result: hr = 0x80070002. The system cannot find the file specified.
 
Assembly manager loaded from:  C:\Windows\Microsoft.NET\Framework64\v4.0.30319\clr.dll
Running under executable  c:\windows\system32\inetsrv\w3wp.exe
--- A detailed error log follows. 

=== Pre-bind state information ===
LOG: User = NT AUTHORITY\NETWORK SERVICE
LOG: DisplayName = Microsoft.Synchronization, Version=2.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91
 (Fully-specified)
LOG: Appbase = file:///C:/Program Files (x86)/MyService.Service/
LOG: Initial PrivatePath = C:\Program Files (x86)\MyService.Service\bin
LOG: Dynamic Base = C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\root\c1449ba8
LOG: Cache Base = C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\root\c1449ba8
LOG: AppName = abf9a5ae
Calling assembly : MyService.Synchronization.ServiceContracts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=08670063761b63a0.
===
LOG: This bind starts in default load context.
LOG: Using application configuration file: C:\Program Files (x86)\MyService.Service\web.config
LOG: Using host configuration file: C:\Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet.config
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework64\v4.0.30319\config\machine.config.
LOG: Post-policy reference: Microsoft.Synchronization, Version=2.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91
LOG: GAC Lookup was unsuccessful.
LOG: Attempting download of new URL file:///C:/Windows/Microsoft.NET/Framework64/v4.0.30319/Temporary ASP.NET Files/root/c1449ba8/abf9a5ae/Microsoft.Synchronization.DLL.
LOG: Attempting download of new URL file:///C:/Windows/Microsoft.NET/Framework64/v4.0.30319/Temporary ASP.NET Files/root/c1449ba8/abf9a5ae/Microsoft.Synchronization/Microsoft.Synchronization.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/MyService.Service/bin/Microsoft.Synchronization.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/MyService.Service/bin/Microsoft.Synchronization/Microsoft.Synchronization.DLL.
LOG: Attempting download of new URL file:///C:/Windows/Microsoft.NET/Framework64/v4.0.30319/Temporary ASP.NET Files/root/c1449ba8/abf9a5ae/Microsoft.Synchronization.EXE.
LOG: Attempting download of new URL file:///C:/Windows/Microsoft.NET/Framework64/v4.0.30319/Temporary ASP.NET Files/root/c1449ba8/abf9a5ae/Microsoft.Synchronization/Microsoft.Synchronization.EXE.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/MyService.Service/bin/Microsoft.Synchronization.EXE.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/MyService.Service/bin/Microsoft.Synchronization/Microsoft.Synchronization.EXE.
LOG: All probing URLs attempted and failed.

In my case I have a binding failure on Sync Framework assemblies. Makes sense since I haven’t installed it yet :).

Tags: , ,

May 20 2010

Richard is blogging

Category: IT RelatedRory Primrose @ 07:05

I’ve finally convinced a work colleague to start blogging is tech experiences. His first tech related post is Simple way to encrypt App.Config through WiX 3.5 and VS2010 Using C# code.

Tags:

May 19 2010

Unity dependency injection for ASP.Net

Category: .NetRory Primrose @ 10:39

I’ve been wanting to get dependency injection happening for ASP.Net pages like I have for WCF service instances (see here and here). The solutions that I found on the net use combinations of abstract ASP.Net pages or Global.asax with an IHttpModule. I didn’t like these solutions because it is messy to make multiple changes to your application to introduce a single piece of functionality.

My version uses a single IHttpModule without any other dependencies. The only impact on the application is to configure the module in web.config.

My UnityHttpModule looks like the following.

using System;
using System.Diagnostics.Contracts;
using System.Web;
using System.Web.UI;
using Microsoft.Practices.Unity;

namespace Neovolve.Toolkit.Unity
{
    public class UnityHttpModule : IHttpModule
    {
        private static readonly Object _syncLock = new Object();

        private static IUnityContainer _container;

        public void Dispose()
        {
            DestroyContainer();
        }

        public void Init(HttpApplication context)
        {
            AssignContainer(UnityContainerResolver.Resolve);

            context.PreRequestHandlerExecute += OnPreRequest;
            context.PostRequestHandlerExecute += OnRequestCompleted;
        }

        private static void AssignContainer(Func<IUnityContainer> getContainer)
        {
            Contract.Ensures(_container != null, "Container was not created");

            if (_container != null)
            {
                return;
            }

            lock (_syncLock)
            {
                // Protect the container against multiple threads and instances that get past the initial check
                if (_container != null)
                {
                    return;
                }

                _container = getContainer();
            }
        }

        private static void DestroyContainer()
        {
            Contract.Ensures(_container == null, "Container was not destroyed");

            if (_container == null)
            {
                return;
            }

            lock (_syncLock)
            {
                // Protect the container against multiple threads and instances that get past the initial check
                if (_container == null)
                {
                    return;
                }

                _container.Dispose();
                _container = null;
            }
        }

        private static void OnPreRequest(Object sender, EventArgs e)
        {
            ProcessUnityAction(sender, page => _container.BuildUp(page.GetType(), page, null));
        }

        private static void OnRequestCompleted(Object sender, EventArgs e)
        {
            ProcessUnityAction(sender, page => _container.Teardown(page));
        }

        private static void ProcessUnityAction(Object sender, Action<Page> unityAction)
        {
            if (sender == null)
            {
                throw new ArgumentNullException("sender");
            }

            if (unityAction == null)
            {
                throw new ArgumentNullException("unityAction");
            }

            if (HttpContext.Current == null)
            {
                return;
            }

            Page page = HttpContext.Current.Handler as Page;

            if (page == null)
            {
                return;
            }

            unityAction(page);
        }

        public static IUnityContainer Container
        {
            get
            {
                return _container;
            }

            set
            {
                AssignContainer(() => value);
            }
        }
    }
}

The UnityHttpModule calls into a UnityContainerResolver helper class to resolve the unity container. The code for UnityContainerResolver can be found here.

The instancing behaviour of IHttpModule must be considered for this implementation as we only want a single container to be used. Many instances of a IHttpModule type get created within an application pool. This is because there are many HttpApplication instances created to satisfy multiple requests for a site. Each HttpApplication instance has it own set of modules. A thread lock is used in this module to protect the static container while it is being assigned or destroyed. The creation of the container happens when the first IHttpModule across any of the the HttpApplications is initialized and the disposal happens when the first IHttpModule is disposed. All other creations and disposals are ignored.

Once created, this module builds up pages with injection values and then tears them down again when the pages are finished with their request processing.

The following is an example ASP.Net page that uses property injection.

using System;
using System.Configuration;
using System.Security.Cryptography;
using System.Text;
using System.Web.UI;
using Microsoft.Practices.Unity;

namespace Neovolve.Toolkit.Unity.WebIntegrationTests
{
    public partial class _Default : Page
    {
        protected void Page_Load(Object sender, EventArgs e)
        {
            if (HashCalculator == null)
            {
                throw new ConfigurationErrorsException("Unity was not used to build up this page");
            }

            String valueToHash = Guid.NewGuid().ToString();
            Byte[] valueInBytes = Encoding.UTF8.GetBytes(valueToHash);
            Byte[] hashBytes = HashCalculator.ComputeHash(valueInBytes);

            Original.Text = valueToHash;
            HashValue.Text = Convert.ToBase64String(hashBytes);
        }

        [Dependency]
        public HashAlgorithm HashCalculator
        {
            get;
            set;
        }
    }
}

The property injection for this page is configured via the web.config. The following example also includes the configuration for the module for both classic and integrated IIS pipeline modes.

<?xml version="1.0" ?>
<configuration>
    <configSections>
        <section name="unity"
                 type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
    </configSections>
    <unity>
        <containers>
            <container>
                <register type="System.Security.Cryptography.HashAlgorithm, mscorlib"
                          mapTo="System.Security.Cryptography.SHA256CryptoServiceProvider, System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
            </container>
        </containers>
    </unity>
    <system.web>
        <compilation debug="true"
                     targetFramework="4.0"/>
        <authentication mode="None"></authentication>
        <httpModules>
            <add type="Neovolve.Toolkit.Unity.UnityHttpModule"
                 name="UnityHttpModule"/>
        </httpModules>
    </system.web>
    <system.webServer>
        <validation validateIntegratedModeConfiguration="false"/>
        <modules runAllManagedModulesForAllRequests="true">
            <add type="Neovolve.Toolkit.Unity.UnityHttpModule"
                 name="UnityHttpModule"/>
        </modules>
    </system.webServer>
</configuration>

The beauty of the way Unity is used here is that you do not need to configure each page that uses injection in the Unity configuration. Only the types being injected need to be defined. There are however a few things to note about this usage:

  • Properties (and their types) that accept injected values must be public
  • Properties that accept injected values must be decorated with the Dependency attribute.
  • Named Unity containers are not supported.
  • Non-standard Unity section configuration names are not supported (must use “unity”)

The only part I do not like about this implementation is that the Unity Dependency attribute must be assigned to the ASP.Net page properties that will use injection. This couples the ASP.Net application to Unity. I suppose a Unity extension could be written to bypass this behaviour, but the attribute is no doubt there for a good reason. My guess is that it caters for scenarios where properties have an associated type in the Unity config but are not intended to have values injected.

The full code for this module with xml comments can be found on my Toolkit project in CodePlex.

Tags: , , ,

May 18 2010

WinMerge support for VS2010 and TFS

Category: .Net | ApplicationsRory Primrose @ 10:12

Back in 2007 I wrote a post about WinMerge support for TFS in Visual Studio. It turned out to be the most hit post on my blog ever since. I have just updated the post with some reg files that add the same support for VS2010 for both x86 and x64 platforms.

Tags:

May 17 2010

Unity dependency injections for WCF services – Part 2

Category: .Net | ApplicationsRory Primrose @ 16:23

In Part 1, I described the code used to leverage ServiceHostFactory to create WCF service instances with dependency injection via Unity. Using a custom ServiceHostFactory is a really easy way to get dependency injection in WCF but comes with two drawbacks. The standard Unity configuration section name (“unity”) must be used and named Unity containers are not supported. Most applications will work within these constraints.

Using a configuration based service behavior is the answer to situations where these constraints are a problem. The UnityServiceElement class is used to define the configuration support for the UnityServiceBehavior. As outlined in the last post, the UnityServiceBehavior class is used to assign a custom instance provider to each endpoint in the service. The instance provider is used to resolve a service instance from a Unity container.

The UnityServiceElement class looks like the following. The UnityServiceElement calls into a UnityContainerResolver helper class to resolve the unity container. The code for UnityContainerResolver can be found here.

using System; 
using System.Configuration;
using System.Diagnostics.Contracts;
using System.ServiceModel.Configuration;
using Microsoft.Practices.Unity;

namespace Neovolve.Toolkit.Unity
{
    public class UnityServiceElement : BehaviorExtensionElement
    {
        public const String UnitySectionNameAttributeName = "unitySectionName";

        private const String UnityContainerNameAttributeName = "unityContainerName";

        private ConfigurationPropertyCollection _properties;

        public override void CopyFrom(ServiceModelExtensionElement from)
        {
            Contract.Requires<ArgumentException>(from is UnityServiceElement, "The from parameter is not of type UnityServiceElement.");

            base.CopyFrom(from);

            UnityServiceElement element = (UnityServiceElement)from;

            UnitySectionName = element.UnitySectionName;
            UnityContainerName = element.UnityContainerName;
        }

        protected override Object CreateBehavior()
        {
            IUnityContainer container = UnityContainerResolver.Resolve(null, UnitySectionName, UnityContainerName);

            return new UnityServiceBehavior(container);
        }

        public override Type BehaviorType
        {
            get
            {
                return typeof(UnityServiceBehavior);
            }
        }

        [ConfigurationProperty(UnityContainerNameAttributeName)]
        public String UnityContainerName
        {
            get
            {
                return (String)base[UnityContainerNameAttributeName];
            }

            set
            {
                base[UnityContainerNameAttributeName] = value;
            }
        }

        [ConfigurationProperty(UnitySectionNameAttributeName)]
        public String UnitySectionName
        {
            get
            {
                return (String)base[UnitySectionNameAttributeName];
            }

            set
            {
                base[UnitySectionNameAttributeName] = value;
            }
        }

        protected override ConfigurationPropertyCollection Properties
        {
            get
            {
                if (_properties == null)
                {
                    ConfigurationPropertyCollection propertys = new ConfigurationPropertyCollection();

                    propertys.Add(
                        new ConfigurationProperty(
                            UnitySectionNameAttributeName, typeof(String), String.Empty, null, null, ConfigurationPropertyOptions.None));

                    propertys.Add(
                        new ConfigurationProperty(
                            UnityContainerNameAttributeName, typeof(String), String.Empty, null, null, ConfigurationPropertyOptions.None));

                    _properties = propertys;
                }

                return _properties;
            }
        }
    }
}

The configuration to hook this behavior up to a service looks like this.

<?xml version="1.0" ?>
<configuration>
    <configSections>
        <section name="customUnitySection"
                 type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
    </configSections>
    <customUnitySection>
        <containers>
            <container name="customContainer">
                <register type="Neovolve.Toolkit.Unity.WebIntegrationTests.TestService, Neovolve.Toolkit.Unity.WebIntegrationTests">
                    <constructor>
                        <param name="prefix">
                            <value value="Injected by custom unity section and container"/>
                        </param>
                    </constructor>
                </register>
            </container>
        </containers>
    </customUnitySection>
    <system.serviceModel>
        <behaviors>
            <serviceBehaviors>
                <behavior name="UnityBehavior">
                    <unityService unitySectionName="customUnitySection"
                                  unityContainerName="customContainer"/>
                </behavior>
            </serviceBehaviors>
        </behaviors>
        <extensions>
            <behaviorExtensions>
                <add name="unityService"
                     type="Neovolve.Toolkit.Unity.UnityServiceElement, Neovolve.Toolkit.Unity, Version=1.0.0.0, Culture=neutral, PublicKeyToken=911824a9aa319cb2"/>
            </behaviorExtensions>
        </extensions>
        <services>
            <service behaviorConfiguration="UnityBehavior"
                     name="Neovolve.Toolkit.Unity.WebIntegrationTests.TestService">
                <endpoint address=""
                          binding="basicHttpBinding"
                          bindingConfiguration=""
                          contract="Neovolve.Toolkit.Unity.WebIntegrationTests.ITestService"/>
            </service>
        </services>
    </system.serviceModel>
</configuration>

The configuration for the element shown here allows for defining custom configuration section and container names for resolving the Unity container.

ServiceHostFactory or configured service behavior

Which one to use?

If you have multiple containers, or a single container that must have a name, then you have no choice but to use the service behavior element as outlined in this post. The only other reason for using the behavior element is if you must use another type of custom factory (such as the WIF WSTrustServiceHostFactory). There really should be no reason to use a non-standard configuration section name for Unity so I don’t think that is a big factor.

Using the ServiceHostFactory is the preferred option as it will result in a slightly cleaner configuration if you are not forced into using a configured service behavior,

The code with xml comments can be found in my Toolkit project on CodePlex.

Tags: , , ,

May 15 2010

Unity dependency injection for WCF services – Part 1

Category: .NetRory Primrose @ 10:26

There are a few ways that Unity can be used to construct WCF service instances. The options are poor mans injection, service host factories and configured behaviours.

The poor mans injection option is to create a unity container within the constructor of the service type and resolve dependencies from within the service instance. This is not elegant and couples the IOC implementation (Unity in this case) to the service.

The second option is to create a custom service host factory. This option allows a service type to be created with constructor dependencies rather than a default constructor. It uses the mark-up in svc files to identify the custom factory to be used rather than the default one. The 4.0 framework also supports this configuration via web.config as svc files are no longer required.

The code goes a bit like this. The UnityServiceHostFactory class is used to define how to create a service host to host the service endpoints. The factory calls into a UnityContainerResolver helper class to resolve the unity container. The code for UnityContainerResolver can be found here.

using System;
using System.ServiceModel;
using System.ServiceModel.Activation;
using Microsoft.Practices.Unity;
using Neovolve.Toolkit.Storage;

namespace Neovolve.Toolkit.Unity
{
    public class UnityServiceHostFactory : ServiceHostFactory
    {
        public UnityServiceHostFactory()
            : this(null, String.Empty, String.Empty)
        {
        }

        public UnityServiceHostFactory(IConfigurationStore configuration, String unitySectionName, String containerName)
        {
            Container = UnityContainerResolver.Resolve(configuration, unitySectionName, containerName);
        }

        public UnityServiceHostFactory(IUnityContainer container)
        {
            if (container == null)
            {
                throw new ArgumentNullException("container");
            }

            Container = container;
        }

        protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
        {
            return new UnityServiceHost(serviceType, Container, baseAddresses);
        }

        public IUnityContainer Container
        {
            get;
            set;
        }
    }
}

The configuration for the factory via svc mark-up is the following.

<%@ ServiceHost 
    Language="C#" 
    Debug="true" 
    Service="Neovolve.Toolkit.Unity.WebIntegrationTests.TestService" 
    Factory="Neovolve.Toolkit.Unity.UnityServiceHostFactory" %>

The configuration via web.config (.net 4.0 only) is like this. This configuration also includes an example Unity container configuration.

<configuration>
    <configSections>
        <section name="unity"
                 type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
    </configSections>
    <unity>
        <containers>
            <container>
                <register type="Neovolve.Toolkit.Unity.WebIntegrationTests.TestService, Neovolve.Toolkit.Unity.WebIntegrationTests">
                    <constructor>
                        <param name="prefix">
                            <value value="Injected by default unity section and container"/>
                        </param>
                    </constructor>
                </register>
            </container>
        </containers>
    </unity>
    <system.serviceModel>
        <serviceHostingEnvironment>
            <serviceActivations>
                <add service="Neovolve.Toolkit.Unity.WebIntegrationTests.TestService" 
                     factory="Neovolve.Toolkit.Unity.UnityServiceHostFactory" 
                     relativeAddress="/TestService.svc" />
            </serviceActivations>
        </serviceHostingEnvironment>
    </system.serviceModel>
</configuration>

The UnityServiceHost class is used to configure the host for a behaviour that is used to create the service instances.

using System;
using System.ServiceModel;
using Microsoft.Practices.Unity;

namespace Neovolve.Toolkit.Unity
{
    internal class UnityServiceHost : ServiceHost
    {
        public UnityServiceHost(Type serviceType, IUnityContainer container, params Uri[] baseAddresses)
            : base(serviceType, baseAddresses)
        {
            if (container == null)
            {
                throw new ArgumentNullException("container");
            }

            Container = container;
        }

        protected override void OnOpening()
        {
            if (Description.Behaviors.Find<UnityServiceBehavior>() == null)
            {
                Description.Behaviors.Add(new UnityServiceBehavior(Container));
            }

            base.OnOpening();
        }

        protected IUnityContainer Container
        {
            get;
            set;
        }
    }
}

The UnityServiceBehavior is used assign a new instance provider to each endpoint in the service host.

using System;
using System.Collections.ObjectModel;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using Microsoft.Practices.Unity;

namespace Neovolve.Toolkit.Unity
{
    internal class UnityServiceBehavior : IServiceBehavior
    {
        public UnityServiceBehavior(IUnityContainer container)
        {
            if (container == null)
            {
                throw new ArgumentNullException("container");
            }

            Container = container;
        }

        public void AddBindingParameters(
            ServiceDescription serviceDescription, 
            ServiceHostBase serviceHostBase, 
            Collection<ServiceEndpoint> endpoints, 
            BindingParameterCollection bindingParameters)
        {
        }

        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            if (serviceDescription == null)
            {
                throw new ArgumentNullException("serviceDescription");
            }

            if (serviceHostBase == null)
            {
                throw new ArgumentNullException("serviceHostBase");
            }

            for (Int32 dispatcherIndex = 0; dispatcherIndex < serviceHostBase.ChannelDispatchers.Count; dispatcherIndex++)
            {
                ChannelDispatcherBase dispatcher = serviceHostBase.ChannelDispatchers[dispatcherIndex];
                ChannelDispatcher channelDispatcher = (ChannelDispatcher)dispatcher;

                for (Int32 endpointIndex = 0; endpointIndex < channelDispatcher.Endpoints.Count; endpointIndex++)
                {
                    EndpointDispatcher endpointDispatcher = channelDispatcher.Endpoints[endpointIndex];

                    endpointDispatcher.DispatchRuntime.InstanceProvider = new UnityInstanceProvider(Container, serviceDescription.ServiceType);
                }
            }
        }

        public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
        }

        protected IUnityContainer Container
        {
            get;
            set;
        }
    }
}

The UnityInstanceProvider is used to resolve an instance from a Unity container using the service type defined for an endpoint. This is where the real work happens to create a service instance with injected dependencies. This implementation also calls the Unity container to destroy the service instance according to its configuration.

using System;
using System.Configuration;
using System.Globalization;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Dispatcher;
using Microsoft.Practices.Unity;

namespace Neovolve.Toolkit.Unity
{
    internal class UnityInstanceProvider : IInstanceProvider
    {
        public UnityInstanceProvider(IUnityContainer container, Type serviceType)
        {
            if (container == null)
            {
                throw new ArgumentNullException("container");
            }

            if (serviceType == null)
            {
                throw new ArgumentNullException("serviceType");
            }

            Container = container;
            ServiceType = serviceType;
        }

        public Object GetInstance(InstanceContext instanceContext)
        {
            return GetInstance(instanceContext, null);
        }

        public Object GetInstance(InstanceContext instanceContext, Message message)
        {
            Object instance = Container.Resolve(ServiceType);

            if (instance == null)
            {
                const String MessageFormat = "No unity configuration was found for service type '{0}'";
                String failureMessage = String.Format(CultureInfo.InvariantCulture, MessageFormat, ServiceType.FullName);

                throw new ConfigurationErrorsException(failureMessage);
            }

            return instance;
        }

        public void ReleaseInstance(InstanceContext instanceContext, Object instance)
        {
            Container.Teardown(instance);
        }

        protected Type ServiceType
        {
            get;
            set;
        }

        private IUnityContainer Container
        {
            get;
            set;
        }
    }
}

That’s it for the custom service host factory code. The one disadvantage with this technique is that there is no configuration support for ServiceHostFactory implementations. The UnityServiceHostFactory is restricted to resolving the default (un-named) container using the standard unity section name of “unity”. If this restriction is not suitable, then a custom UnityServiceBehavior must be used.

Part 2 will look at leveraging the UnityServiceBehavior directly via configuration rather than going through a factory.

The code with xml comments can be found in my Tookit project on CodePlex.

Tags: , ,