1 //------------------------------------------------------------
2 // Copyright (c) Microsoft Corporation.  All rights reserved.
3 //------------------------------------------------------------
4 namespace System.ServiceModel.Channels
5 {
6     using System;
7     using System.Threading;
8     using System.Security.Authentication.ExtendedProtection;
9 
10     sealed class ChannelBindingMessageProperty : IDisposable, IMessageProperty
11     {
12         const string propertyName = "ChannelBindingMessageProperty";
13 
14         ChannelBinding channelBinding;
15         object thisLock;
16         bool ownsCleanup;
17         int refCount;
18 
ChannelBindingMessageProperty(ChannelBinding channelBinding, bool ownsCleanup)19         public ChannelBindingMessageProperty(ChannelBinding channelBinding, bool ownsCleanup)
20         {
21             if (channelBinding == null)
22             {
23                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("channelBinding");
24             }
25 
26             this.refCount = 1;
27             this.thisLock = new object();
28             this.channelBinding = channelBinding;
29             this.ownsCleanup = ownsCleanup;
30         }
31 
32         public static string Name { get { return propertyName; } }
33 
34         bool IsDisposed
35         {
36             get
37             {
38                 return this.refCount <= 0;
39             }
40         }
41 
42         public ChannelBinding ChannelBinding
43         {
44             get
45             {
46                 ThrowIfDisposed();
47                 return this.channelBinding;
48             }
49         }
50 
TryGet(Message message, out ChannelBindingMessageProperty property)51         public static bool TryGet(Message message, out ChannelBindingMessageProperty property)
52         {
53             if (message == null)
54             {
55                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("message");
56             }
57 
58             return TryGet(message.Properties, out property);
59         }
60 
TryGet(MessageProperties properties, out ChannelBindingMessageProperty property)61         public static bool TryGet(MessageProperties properties, out ChannelBindingMessageProperty property)
62         {
63             if (properties == null)
64             {
65                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("properties");
66             }
67 
68             property = null;
69             object value;
70 
71             if (properties.TryGetValue(ChannelBindingMessageProperty.Name, out value))
72             {
73                 property = value as ChannelBindingMessageProperty;
74                 return property != null;
75             }
76 
77             return false;
78         }
79 
AddTo(Message message)80         public void AddTo(Message message)
81         {
82             if (message == null)
83             {
84                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("message");
85             }
86 
87             AddTo(message.Properties);
88         }
89 
AddTo(MessageProperties properties)90         public void AddTo(MessageProperties properties)
91         {
92             ThrowIfDisposed();
93             if (properties == null)
94             {
95                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("properties");
96             }
97 
98             properties.Add(ChannelBindingMessageProperty.Name, this);
99         }
100 
CreateCopy()101         public IMessageProperty CreateCopy()
102         {
103             lock (this.thisLock)
104             {
105                 ThrowIfDisposed();
106                 this.refCount++;
107                 return this;
108             }
109         }
110 
Dispose()111         public void Dispose()
112         {
113             if (!this.IsDisposed)
114             {
115                 lock (this.thisLock)
116                 {
117                     if (!this.IsDisposed && --this.refCount == 0)
118                     {
119                         if (ownsCleanup)
120                         {
121                             // Accessing via IDisposable to avoid Security check (functionally the same)
122                             ((IDisposable)this.channelBinding).Dispose();
123                         }
124                     }
125                 }
126             }
127         }
128 
ThrowIfDisposed()129         void ThrowIfDisposed()
130         {
131             if (this.IsDisposed)
132             {
133                 throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ObjectDisposedException(this.GetType().FullName));
134             }
135         }
136     }
137 }
138