2 // TransactionFlowBindingElement.cs
5 // Atsushi Enomoto <atsushi@ximian.com>
7 // Copyright (C) 2006 Novell, Inc. http://www.novell.com
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 using System.Collections.Generic;
30 using System.ServiceModel.Description;
31 using System.ServiceModel.Security;
32 using System.ServiceModel.Channels;
33 using System.Transactions;
35 namespace System.ServiceModel.Channels
37 public class TransactionFlowBindingElement : BindingElement
39 TransactionProtocol protocol;
41 // Funny, but since it uses OLE TX, Mono will never support this constructor.
43 public TransactionFlowBindingElement ()
44 : this (TransactionProtocol.Default)
48 public TransactionFlowBindingElement (TransactionProtocol transactionProtocol)
50 this.protocol = transactionProtocol;
53 public TransactionProtocol TransactionProtocol {
54 get { return protocol; }
57 public override BindingElement Clone ()
59 return new TransactionFlowBindingElement (protocol);
63 public override T GetProperty<T> (BindingContext context)
65 return context.GetInnerProperty<T> ();
68 public override bool CanBuildChannelFactory<TChannel> (BindingContext context)
70 return context.CanBuildInnerChannelFactory<TChannel> ();
74 public override bool CanBuildChannelListener<TChannel> (BindingContext context)
76 return context.CanBuildInnerChannelListener<TChannel> ();
79 public override IChannelFactory<TChannel> BuildChannelFactory<TChannel> (BindingContext context)
82 throw new InvalidOperationException ("Set transaction protocol in prior to build a channel factory.");
83 if (protocol == TransactionProtocol.Default)
84 throw new NotSupportedException ("Mono does not support DTC.");
85 if (!CanBuildChannelFactory<TChannel> (context.Clone ()))
86 throw new ArgumentException (String.Format ("The channel type '{0}' is not supported", typeof (TChannel)));
87 return new TransactionChannelFactory<TChannel> (context.BuildInnerChannelFactory<TChannel> (), protocol);
90 public override IChannelListener<TChannel> BuildChannelListener<TChannel> (BindingContext context)
93 throw new InvalidOperationException ("Set transaction protocol in prior to build a channel listener.");
94 if (protocol == TransactionProtocol.Default)
95 throw new NotSupportedException ("Mono does not support DTC.");
96 if (!CanBuildChannelListener<TChannel> (context.Clone ()))
97 throw new ArgumentException (String.Format ("The channel type '{0}' is not supported", typeof (TChannel)));
98 return new TransactionChannelListener<TChannel> (
99 context.BuildInnerChannelListener<TChannel> (),
104 internal class TransactionChannelFactory<TChannel> : ChannelFactoryBase<TChannel>
106 IChannelFactory<TChannel> inner_factory;
107 TransactionScope txscope;
108 TransactionProtocol protocol;
110 public TransactionChannelFactory (IChannelFactory<TChannel> innerFactory, TransactionProtocol protocol)
112 this.inner_factory = innerFactory;
113 this.protocol = protocol;
118 CommittableTransaction tx = new CommittableTransaction ();
119 txscope = new TransactionScope (tx);
122 protected override void OnOpen (TimeSpan timeout)
125 inner_factory.Open (timeout);
128 protected override IAsyncResult OnBeginOpen (TimeSpan timeout, AsyncCallback callback, object state)
131 return inner_factory.BeginOpen (timeout, callback, state);
134 protected override void OnEndOpen (IAsyncResult result)
136 inner_factory.EndOpen (result);
139 protected override TChannel OnCreateChannel (
140 EndpointAddress remoteAddress, Uri via)
142 return inner_factory.CreateChannel (remoteAddress, via);
145 protected override void OnClose (TimeSpan timeout)
147 inner_factory.Close (timeout);
152 internal class TransactionChannelListener<TChannel> : ChannelListenerBase<TChannel> where TChannel : class, IChannel
154 IChannelListener<TChannel> inner_listener;
155 TransactionScope txscope;
156 TransactionProtocol protocol;
158 public TransactionChannelListener (IChannelListener<TChannel> innerListener, TransactionProtocol protocol)
160 this.inner_listener = innerListener;
161 this.protocol = protocol;
164 public override T GetProperty<T> ()
166 return inner_listener.GetProperty<T> () ?? base.GetProperty<T> ();
169 public override Uri Uri {
170 get { return inner_listener.Uri; }
173 protected override void OnAbort ()
175 inner_listener.Abort ();
178 protected override void OnOpen (TimeSpan timeout)
180 CommittableTransaction tx = new CommittableTransaction ();
181 txscope = new TransactionScope (tx);
182 inner_listener.Open (timeout);
185 protected override IAsyncResult OnBeginOpen (TimeSpan timeout, AsyncCallback callback, object state)
187 return inner_listener.BeginOpen (timeout, callback, state);
190 protected override void OnEndOpen (IAsyncResult result)
192 inner_listener.EndOpen (result);
195 protected override void OnClose (TimeSpan timeout)
197 inner_listener.Close (timeout);
201 protected override IAsyncResult OnBeginClose (TimeSpan timeout, AsyncCallback callback, object state)
203 return inner_listener.BeginClose (timeout, callback, state);
206 protected override void OnEndClose (IAsyncResult result)
208 inner_listener.EndClose (result);
211 protected override bool OnWaitForChannel (TimeSpan timeout)
213 return inner_listener.WaitForChannel (timeout);
216 protected override IAsyncResult OnBeginWaitForChannel (TimeSpan timeout, AsyncCallback callback, object state)
218 return inner_listener.BeginWaitForChannel (timeout, callback, state);
221 protected override bool OnEndWaitForChannel (IAsyncResult result)
223 return inner_listener.EndWaitForChannel (result);
226 protected override TChannel OnAcceptChannel (TimeSpan timeout)
228 return inner_listener.AcceptChannel (timeout);
231 protected override IAsyncResult OnBeginAcceptChannel (TimeSpan timeout,
232 AsyncCallback callback, object asyncState)
234 return inner_listener.BeginAcceptChannel (timeout, callback, asyncState);
237 protected override TChannel OnEndAcceptChannel (IAsyncResult result)
239 return inner_listener.EndAcceptChannel (result);