Assuming you already have your domain model and repositories implemented and unity wired (if you are missing this part, let me know and i'll add the full stack on a blog), traditionally being consumed by a asp.net MVC3 application, I have added a service assembly that pretty much implements the basic business logic on the repository querying (i leave the heavy processes to a fsharp component) . this would look like the below:
public interface IExampleService
{
IEnumerable<Example> GetAll();
}
public class ExampleService : IExampleService
{
private readonly IExampleRepository ExampleRepository;
private readonly IUnitOfWork unitOfWork;
public ConfigService(IConfigRepository exampleRepository, IUnitOfWork unitOfWork)
{
this.ExampleRepository = exampleRepository;
this.unitOfWork = unitOfWork;
}
public IEnumerable<Config> GetAll()
{
var categories = ConfigRepository.GetAll();
return categories;
}
}
Now, let's say you badly want to wire this to wcf with unity.
That's how you do it. Create a new class file and dump the code below:
using System.ServiceModel.Dispatcher;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Channels;
using System.Collections.ObjectModel;
namespace Example.Rest.Helpers
{
public class IoC
{
public class UnityWebServiceHost : WebServiceHost
{
protected IUnityContainer _container;
public UnityWebServiceHost()
{
}
public UnityWebServiceHost(object singletonInstance, params Uri[] baseAddresses)
: base(singletonInstance, baseAddresses)
{
}
public UnityWebServiceHost(IUnityContainer container, Type serviceType, params Uri[] baseAddresses)
: base(serviceType, baseAddresses)
{
if (container == null)
{
throw new ArgumentNullException("container");
}
_container = container;
}
protected override void OnOpening()
{
Description.Behaviors.Add(new UnityServiceBehaviour(_container));
base.OnOpening();
}
}
public class UnityInstanceProvider : IInstanceProvider
{
private readonly Type _serviceType;
private readonly IUnityContainer _container;
public UnityInstanceProvider(IUnityContainer container, Type serviceType)
{
_serviceType = serviceType;
_container = container;
}
public object GetInstance(InstanceContext instanceContext)
{
return GetInstance(instanceContext, null);
}
public object GetInstance(InstanceContext instanceContext, Message message)
{
return _container.Resolve(_serviceType);
}
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
}
}
public class HttpContextLifetimeManager<T> : LifetimeManager, IDisposable
{
public override object GetValue()
{
return HttpContext.Current.Items[typeof(T).AssemblyQualifiedName];
}
public override void RemoveValue()
{
HttpContext.Current.Items.Remove(typeof(T).AssemblyQualifiedName);
}
public override void SetValue(object newValue)
{
HttpContext.Current.Items[typeof(T).AssemblyQualifiedName] = newValue;
}
public void Dispose()
{
RemoveValue();
}
}
public class UnityServiceBehaviour : IServiceBehavior
{
private readonly IUnityContainer _container;
public UnityServiceBehaviour(IUnityContainer container)
{
_container = container;
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (var endpointDispatcher in
serviceHostBase.ChannelDispatchers.OfType<ChannelDispatcher>().SelectMany(
channelDispatcher => channelDispatcher.Endpoints))
{
endpointDispatcher.DispatchRuntime.InstanceProvider = new UnityInstanceProvider(_container, serviceDescription.ServiceType);
}
}
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase,
Collection<ServiceEndpoint> endpoints,
BindingParameterCollection bindingParameters)
{
}
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
}
}
}
}
Okay, Let's setup a wcf rest service:
[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class ExampleApi
{
private readonly IExampleService exampleService;
public ExampleApi(IExampleService exampleService)
{
this.exampleService = exampleService;
}
public exampleApi()
{
}
[WebGet(UriTemplate = "")]
public IEnumerable<Example> GetAll()
{
var examples = exampleService.GetAll();
return examples;
}
}
Now, insure your WCFrest app global.asax file looks like the following, so we use our custom UnityServiceHostFactory and register our dependencies:
public class Global : HttpApplication
{
void Application_Start(object sender, EventArgs e)
{
RegisterRoutes();
}
private void RegisterRoutes()
{
RouteTable.Routes.Add(new ServiceRoute("ExampleApi", new UnityServiceHostFactory(), typeof(ExampleApi)));
}
private static void RegisterTypes(IUnityContainer container)
{
container.RegisterType<IDatabaseFactory, DatabaseFactory>(new IoC.HttpContextLifetimeManager<IDatabaseFactory>());
container.RegisterType<IUnitOfWork, UnitOfWork>(new IoC.HttpContextLifetimeManager<IUnitOfWork>());
// repositories
container.RegisterType<IExampleRepository, ExampleRepository>(new IoC.HttpContextLifetimeManager<IExampleRepository>());
// services
container.RegisterType<IExampleService, ExampleService>(new IoC.HttpContextLifetimeManager<IExampleService>());
}
public class UnityServiceHostFactory : WebServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
var container = new UnityContainer();
RegisterTypes(container);
return new IoC.UnityWebServiceHost(container, serviceType, baseAddresses);
}
}
}
That's all folks.