#region File and License Information
/*
<File>
<Copyright>Copyright © 2007, Daniel Vaughan. All rights reserved.</Copyright>
<License see="prj:///Documentation/License.txt"/>
<Owner Name="Daniel Vaughan" Email="dbvaughan@gmail.com"/>
<CreationDate>2008-11-03 23:13:11Z</CreationDate>
<LastSubmissionDate>$Date: $</LastSubmissionDate>
<Version>$Revision: $</Version>
</File>
*/
#endregion
using System;
using System.Reflection;
using DanielVaughan.Concurrency;
namespace DanielVaughan
{
/// <summary>
/// Use to invoke an asynchronous WCF service method synchronously.
/// </summary>
public delegate IAsyncResult BeginAction(AsyncCallback asyncResult, object state);
public delegate IAsyncResult BeginAction<TActionArgument1>(TActionArgument1 argument1, AsyncCallback asyncResult, object state);
public delegate IAsyncResult BeginAction<TActionArgument1, TActionArgument2>(TActionArgument1 argument1, TActionArgument2 argument2, AsyncCallback asyncResult, object state);
public delegate IAsyncResult BeginAction<TActionArgument1, TActionArgument2, TActionArgument3>(TActionArgument1 argument1, TActionArgument2 argument2, TActionArgument3 argument3, AsyncCallback asyncResult, object state);
public delegate IAsyncResult BeginAction<TActionArgument1, TActionArgument2, TActionArgument3, TActionArgument4>(TActionArgument1 argument1, TActionArgument2 argument2, TActionArgument3 argument3, TActionArgument4 argument4, AsyncCallback asyncResult, object state);
public delegate void EndAction(IAsyncResult asyncResult);
public delegate TReturn EndAction<TReturn>(IAsyncResult asyncResult);
/// <summary>
/// Enables one to call asynchronous WCF services,
/// via generated proxies, in a synchronous manner.
/// </summary>
public static class SynchronousChannelBroker
{
const string synchronousCallInvalidMessage = "Synchronous WCF call can not be performed from UI Thread.";
static void EnsureNonUIThread()
{
if (!UISynchronizationContext.Instance.InvokeRequired)
{
throw new ConcurrencyException(synchronousCallInvalidMessage);
}
}
#region Return type specified
/// <summary>
/// Performs the action synchronously.
/// </summary>
/// <exception cref="ConcurrencyException">Occurs if the call is executed from the UI thread.</exception>
/// <exception cref="TargetInvocationException">Occurs if the specified <code>endAction</code>
/// throws a <code>TargetInvocationException</code></exception>
/// <typeparam name="TReturn">The type of the object returned by the specified <code>endAction</code>.</typeparam>
/// <param name="beginAction">The Begin[MethodName] method.</param>
/// <param name="endAction">The End[MethodName] method.</param>
/// <returns>The result of the <code>EndAction</code> method.</returns>
/// <example>
/// try
/// {
/// /* Perform synchronous WCF call. */
/// result = SynchronousChannelBroker.PerformAction<string>(
/// someService.BeginGetString, someService.EndGetString);
/// }
/// catch (TargetInvocationException ex)
/// {
/// DisplayMessage(string.Format("Unable to communicate with server. {0} {1}",
/// ex.Message, ex.StackTrace));
/// }
/// </example>
public static TReturn PerformAction<TReturn>(BeginAction beginAction, EndAction<TReturn> endAction)
{
EnsureNonUIThread();
var beginResult = beginAction(null, null);
var result = endAction(beginResult);
return result;
}
/// <summary>
/// Performs the action synchronously.
/// </summary>
/// <exception cref="ConcurrencyException">Occurs if the call is executed from the UI thread.</exception>
/// <exception cref="TargetInvocationException">Occurs if the specified <code>endAction</code>
/// throws a <code>TargetInvocationException</code></exception>
/// <typeparam name="TReturn">The type of the object returned
/// by the specified <code>endAction</code>.</typeparam>
/// <typeparam name="TActionArgument1">The type of the argument required
/// by the specified <code>BeginAction</code>.</typeparam>
/// <param name="beginAction">The Begin[MethodName] method.</param>
/// <param name="endAction">The End[MethodName] method.</param>
/// <param name="argument1">The argument required by the specified <code>BeginAction</code></param>
/// <returns>The result of the <code>EndAction</code> method.</returns>
/// <example>
/// try
/// {
/// /* Perform synchronous WCF call. */
/// result = SynchronousChannelBroker.PerformAction<string, string>(
/// someService.BeginGetString, someService.EndGetString, "test string");
/// }
/// catch (TargetInvocationException ex)
/// {
/// DisplayMessage(string.Format("Unable to communicate with server. {0} {1}",
/// ex.Message, ex.StackTrace));
/// }
/// </example>
public static TReturn PerformAction<TReturn, TActionArgument1>(
Func<TActionArgument1, AsyncCallback, object, IAsyncResult> beginAction,
Func<IAsyncResult, TReturn> endAction, TActionArgument1 argument1)
{
EnsureNonUIThread();
var beginResult = beginAction(argument1, null, null);
var result = endAction(beginResult);
return result;
}
/// <summary>
/// Performs the action synchronously.
/// </summary>
/// <exception cref="ConcurrencyException">Occurs if the call is executed from the UI thread.</exception>
/// <exception cref="TargetInvocationException">Occurs if the specified <code>endAction</code>
/// throws a <code>TargetInvocationException</code></exception>
/// <typeparam name="TReturn">The type of the object returned
/// by the specified <code>endAction</code>.</typeparam>
/// <typeparam name="TActionArgument1">The type of the first argument required
/// by the specified <code>BeginAction</code>.</typeparam>
/// <typeparam name="TActionArgument2">The type of the second argument required
/// by the specified <code>BeginAction</code>.</typeparam>
/// <param name="beginAction">The Begin[MethodName] method.</param>
/// <param name="endAction">The End[MethodName] method.</param>
/// <param name="argument1">The first argument required by the specified <code>BeginAction</code></param>
/// <param name="argument2">The second argument required by the specified <code>BeginAction</code></param>
/// <returns>The result of the <code>EndAction</code> method.</returns>
/// <example>
/// string result;
/// try
/// {
/// /* Perform synchronous WCF call. */
/// result = SynchronousChannelBroker.PerformAction<string, string, int>(
/// someService.BeginGetString, someService.EndGetString, "test string", 5);
/// }
/// catch (TargetInvocationException ex)
/// {
/// DisplayMessage(string.Format("Unable to communicate with server. {0} {1}",
/// ex.Message, ex.StackTrace));
/// }
/// </example>
public static TReturn PerformAction<TReturn, TActionArgument1, TActionArgument2>(
BeginAction<TActionArgument1, TActionArgument2> beginAction,
EndAction<TReturn> endAction,
TActionArgument1 argument1, TActionArgument2 argument2)
{
EnsureNonUIThread();
var beginResult = beginAction(argument1, argument2, null, null);
var result = endAction(beginResult);
return result;
}
public static TReturn PerformAction<TReturn, TActionArgument1, TActionArgument2, TActionArgument3>(
BeginAction<TActionArgument1, TActionArgument2, TActionArgument3> action,
EndAction<TReturn> endAction,
TActionArgument1 argument1, TActionArgument2 argument2, TActionArgument3 argument3)
{
EnsureNonUIThread();
var beginResult = action(argument1, argument2, argument3, null, null);
var result = endAction(beginResult);
return result;
}
public static TReturn PerformAction<TReturn, TActionArgument1, TActionArgument2, TActionArgument3, TActionArgument4>(
BeginAction<TActionArgument1, TActionArgument2, TActionArgument3, TActionArgument4> action,
EndAction<TReturn> endAction,
TActionArgument1 argument1, TActionArgument2 argument2, TActionArgument3 argument3, TActionArgument4 argument4)
{
EnsureNonUIThread();
var beginResult = action(argument1, argument2, argument3, argument4, null, null);
var result = endAction(beginResult);
return result;
}
#endregion
#region void return type
/// <summary>
/// Performs the action synchronously.
/// </summary>
/// <exception cref="ConcurrencyException">Occurs if the call is executed from the UI thread.</exception>
/// <exception cref="TargetInvocationException">Occurs if the specified <code>endAction</code>
/// throws a <code>TargetInvocationException</code></exception>
/// <param name="beginAction">The Begin[MethodName] method.</param>
/// <param name="endAction">The End[MethodName] method.</param>
/// <returns>The result of the <code>EndAction</code> method.</returns>
/// <example>
/// try
/// {
/// /* Perform synchronous WCF call. */
/// SynchronousChannelBroker.PerformAction<string>(
/// someService.BeginGetString, someService.EndGetString, "test string");
/// }
/// catch (TargetInvocationException ex)
/// {
/// DisplayMessage(string.Format("Unable to communicate with server. {0} {1}",
/// ex.Message, ex.StackTrace));
/// }
/// </example>
public static void PerformAction(BeginAction beginAction, EndAction endAction)
{
EnsureNonUIThread();
var beginResult = beginAction(null, null);
endAction(beginResult);
}
/// <summary>
/// Performs the action synchronously.
/// </summary>
/// <exception cref="ConcurrencyException">Occurs if the call is executed from the UI thread.</exception>
/// <exception cref="TargetInvocationException">Occurs if the specified <code>endAction</code>
/// throws a <code>TargetInvocationException</code></exception>
/// <param name="beginAction">The Begin[MethodName] method.</param>
/// <param name="endAction">The End[MethodName] method.</param>
/// <param name="argument1">The first argument required
/// by the specified <code>BeginAction</code></param>
/// <returns>The result of the <code>EndAction</code> method.</returns>
/// <example>
/// try
/// {
/// /* Perform synchronous WCF call. */
/// SynchronousChannelBroker.PerformAction(
/// someService.BeginGetString, someService.EndGetString);
/// }
/// catch (TargetInvocationException ex)
/// {
/// DisplayMessage(string.Format("Unable to communicate with server. {0} {1}",
/// ex.Message, ex.StackTrace));
/// }
/// </example>
public static void PerformAction<TActionArgument1>(
BeginAction<TActionArgument1> beginAction,
EndAction endAction,
TActionArgument1 argument1)
{
EnsureNonUIThread();
var beginResult = beginAction(argument1, null, null);
endAction(beginResult);
}
public static void PerformAction<TActionArgument1, TActionArgument2>(
BeginAction<TActionArgument1, TActionArgument2> action,
EndAction endAction,
TActionArgument1 argument1, TActionArgument2 argument2)
{
EnsureNonUIThread();
var beginResult = action(argument1, argument2, null, null);
endAction(beginResult);
}
public static void PerformAction<TActionArgument1, TActionArgument2, TActionArgument3>(
BeginAction<TActionArgument1, TActionArgument2, TActionArgument3> action,
EndAction endAction,
TActionArgument1 argument1, TActionArgument2 argument2, TActionArgument3 argument3)
{
EnsureNonUIThread();
var beginResult = action(argument1, argument2, argument3, null, null);
endAction(beginResult);
}
public static void PerformAction<TActionArgument1, TActionArgument2, TActionArgument3, TActionArgument4>(
BeginAction<TActionArgument1, TActionArgument2, TActionArgument3, TActionArgument4> action,
EndAction endAction,
TActionArgument1 argument1, TActionArgument2 argument2, TActionArgument3 argument3, TActionArgument4 argument4)
{
EnsureNonUIThread();
var beginResult = action(argument1, argument2, argument3, argument4, null, null);
endAction(beginResult);
}
#endregion
}
}