using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Threading; using System.ServiceModel.Description; using System.ServiceModel.Dispatcher; using System.ServiceModel.Channels; [AttributeUsage(AttributeTargets.Method)] class StaSyncOperationBehaviorAttribute : Attribute, IOperationBehavior { public void Validate(OperationDescription operationDescription) { if (operationDescription.SyncMethod == null) { throw new InvalidOperationException("The StaSyncOperationBehaviorAttribute only works for Synchronous methods. OperationDescription.SyncMethod returned 'null'."); } } public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation) { if (dispatchOperation.Invoker.IsSynchronous == false) { throw new InvalidOperationException("The StaSyncOperationBehaviorAttribute only works for Synchronous methods. DispatchOperatoin.Invoker.IsSynchronous returned 'false'."); } dispatchOperation.Invoker = new StaOperationSyncInvoker(dispatchOperation.Invoker); } public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters) { } public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation) { } class StaOperationSyncInvoker : IOperationInvoker { private readonly IOperationInvoker _innerInvoker; public StaOperationSyncInvoker(IOperationInvoker innerInvoker) { _innerInvoker = innerInvoker; } public object[] AllocateInputs() { return _innerInvoker.AllocateInputs(); } class InvokeDelegateArgs { public IOperationInvoker Invoker { get; set; } public Object Instance { get; set; } public Object[] Inputs { get; set; } public Object[] Outputs { get; set; } public Object ReturnValue { get; set; } public InvokeDelegateArgs(IOperationInvoker invoker, object instance, object[] inputs) { Invoker = invoker; Instance = instance; Inputs = inputs; } } static void InvokeDelegate(object data) { InvokeDelegateArgs ida = (InvokeDelegateArgs)data; Object[] outputs; ida.ReturnValue = ida.Invoker.Invoke(ida.Instance, ida.Inputs, out outputs); ida.Outputs = outputs; } public object Invoke(object instance, object[] inputs, out object[] outputs) { InvokeDelegateArgs ida = new InvokeDelegateArgs(_innerInvoker, instance, inputs); Thread t = new Thread(InvokeDelegate); t.SetApartmentState(ApartmentState.STA); t.Start(ida); t.Join(); outputs = ida.Outputs; return ida.ReturnValue; } public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state) { throw new NotImplementedException(); } public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result) { throw new NotImplementedException(); } public bool IsSynchronous { get { return _innerInvoker.IsSynchronous; } } } }