coreycoto
05-06-2008, 03:19 PM
After some frustraition, I have developed a solution that enables the use NHibernate's Lazy Initialization within WCF Webservices. I was only able to do so by standing on the shoulders of those who came before me (stienard and crabo).
public class ServiceOpenSessionInViewModule : IDisposable
{
private OpenSessionInViewModule osiv;
public ServiceOpenSessionInViewModule(OpenSessionInViewMo dule osiv)
{
this.osiv = osiv;
this.osiv.Open();
}
public void Dispose()
{
osiv.Close();
}
}
public class ServiceOpenSessionInViewInvoker : IOperationInvoker
{
private IOperationInvoker innerOperationInvoker;
public ServiceOpenSessionInViewInvoker(IOperationInvoker innerOperationInvoker)
{
this.innerOperationInvoker = innerOperationInvoker;
}
public object[] AllocateInputs()
{
return this.innerOperationInvoker.AllocateInputs();
}
public object Invoke(object instance, object[] inputs, out object[] outputs)
{
object value;
using (new ServiceOpenSessionInViewModule(new OpenSessionInViewModule()))
{
value = this.innerOperationInvoker.Invoke(instance, inputs, out outputs);
}
return value;
}
public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state)
{
return innerOperationInvoker.InvokeBegin(instance, inputs, callback, state);
}
public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result)
{
return innerOperationInvoker.InvokeEnd(instance, out outputs, result);
}
public bool IsSynchronous
{
get { return innerOperationInvoker.IsSynchronous; }
}
}
[AttributeUsage(AttributeTargets.Method)]
public class ServiceOpenSessionInViewBehaviorAttribute : Attribute, IOperationBehavior
{
public void Validate(OperationDescription operationDescription)
{
if (operationDescription.SyncMethod == null)
{
StringBuilder sb = new StringBuilder();
sb.Append("The ServiceOpenSessionInViewBehaviorAttribute only works for Synchronous methods. ");
sb.Append("OperationDescription.SyncMethod returned 'null'.");
throw new InvalidOperationException(sb.ToString());
}
}
public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
{
if (dispatchOperation.Invoker.IsSynchronous == false)
{
StringBuilder sb = new StringBuilder();
sb.Append("The ServiceOpenSessionInViewBehaviorAttribute only works for Synchronous methods. ");
sb.Append("OperationDescription.SyncMethod returned 'false'.");
throw new InvalidOperationException(sb.ToString());
}
dispatchOperation.Invoker = new ServiceOpenSessionInViewInvoker(dispatchOperation. Invoker);
}
public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
{
}
}
Add the following method attribute to your WCF Service Method:
[ServiceOpenSessionInViewBehavior]
public String GetMessage(int messageId)
{
//Execute NHibernate query
return "Hello World";
}
The implementation has been working pretty successfully for me. Please let me know if you have any questions or suggestions.
Thanks,
Corey
public class ServiceOpenSessionInViewModule : IDisposable
{
private OpenSessionInViewModule osiv;
public ServiceOpenSessionInViewModule(OpenSessionInViewMo dule osiv)
{
this.osiv = osiv;
this.osiv.Open();
}
public void Dispose()
{
osiv.Close();
}
}
public class ServiceOpenSessionInViewInvoker : IOperationInvoker
{
private IOperationInvoker innerOperationInvoker;
public ServiceOpenSessionInViewInvoker(IOperationInvoker innerOperationInvoker)
{
this.innerOperationInvoker = innerOperationInvoker;
}
public object[] AllocateInputs()
{
return this.innerOperationInvoker.AllocateInputs();
}
public object Invoke(object instance, object[] inputs, out object[] outputs)
{
object value;
using (new ServiceOpenSessionInViewModule(new OpenSessionInViewModule()))
{
value = this.innerOperationInvoker.Invoke(instance, inputs, out outputs);
}
return value;
}
public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state)
{
return innerOperationInvoker.InvokeBegin(instance, inputs, callback, state);
}
public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result)
{
return innerOperationInvoker.InvokeEnd(instance, out outputs, result);
}
public bool IsSynchronous
{
get { return innerOperationInvoker.IsSynchronous; }
}
}
[AttributeUsage(AttributeTargets.Method)]
public class ServiceOpenSessionInViewBehaviorAttribute : Attribute, IOperationBehavior
{
public void Validate(OperationDescription operationDescription)
{
if (operationDescription.SyncMethod == null)
{
StringBuilder sb = new StringBuilder();
sb.Append("The ServiceOpenSessionInViewBehaviorAttribute only works for Synchronous methods. ");
sb.Append("OperationDescription.SyncMethod returned 'null'.");
throw new InvalidOperationException(sb.ToString());
}
}
public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
{
if (dispatchOperation.Invoker.IsSynchronous == false)
{
StringBuilder sb = new StringBuilder();
sb.Append("The ServiceOpenSessionInViewBehaviorAttribute only works for Synchronous methods. ");
sb.Append("OperationDescription.SyncMethod returned 'false'.");
throw new InvalidOperationException(sb.ToString());
}
dispatchOperation.Invoker = new ServiceOpenSessionInViewInvoker(dispatchOperation. Invoker);
}
public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
{
}
public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
{
}
}
Add the following method attribute to your WCF Service Method:
[ServiceOpenSessionInViewBehavior]
public String GetMessage(int messageId)
{
//Execute NHibernate query
return "Hello World";
}
The implementation has been working pretty successfully for me. Please let me know if you have any questions or suggestions.
Thanks,
Corey