Line data Source code
1 : #region Copyright
2 : // -----------------------------------------------------------------------
3 : // <copyright company="Chinchilla Software Limited">
4 : // Copyright Chinchilla Software Limited. All rights reserved.
5 : // </copyright>
6 : // -----------------------------------------------------------------------
7 : #endregion
8 :
9 : using System;
10 : using System.Runtime.Serialization;
11 : using System.Xml;
12 : using Cqrs.Authentication;
13 :
14 : namespace Cqrs.Services
15 : {
16 : /// <summary>
17 : /// A <see cref="DataContractResolver"/> for use via WCF that ensures basic support for
18 : /// <see cref="ServiceResponse"/>, <see cref="ServiceRequest{TAuthenticationToken}"/>
19 : /// and anything <see cref="TokenResolver"/> and <see cref="EventDataResolver"/> support.
20 : /// </summary>
21 : /// <typeparam name="TServiceParameter">The <see cref="Type"/> of the service to include in the <see cref="ServiceNamespace"/>.</typeparam>
22 : /// <typeparam name="TAuthenticationToken">The <see cref="Type"/> of authentication token.</typeparam>
23 : public abstract class BasicServiceParameterResolver<TServiceParameter, TAuthenticationToken> : DataContractResolver, IServiceParameterResolver
24 1 : {
25 : /// <summary>
26 : /// Instantiates a new instance of <see cref="BasicServiceParameterResolver{TServiceParameter,TAuthenticationToken}"/>.
27 : /// </summary>
28 1 : protected BasicServiceParameterResolver(ISingleSignOnTokenResolver tokenResolver, IEventDataResolver eventDataResolver)
29 : {
30 : TokenResolver = tokenResolver;
31 : EventDataResolver = eventDataResolver;
32 : ServiceNamespace = string.Format("https://getcqrs.net/{0}", typeof(TServiceParameter).FullName);
33 : }
34 :
35 : /// <summary>
36 : /// Instantiates a new instance of <see cref="BasicServiceParameterResolver{TServiceParameter,TAuthenticationToken}"/>
37 : /// defaulting <see cref="TokenResolver"/> to <see cref="BasicTokenResolver"/>.
38 : /// </summary>
39 1 : protected BasicServiceParameterResolver(IEventDataResolver eventDataResolver)
40 : {
41 : TokenResolver = new BasicTokenResolver();
42 : EventDataResolver = eventDataResolver;
43 : ServiceNamespace = string.Format("https://getcqrs.net/{0}", typeof(TServiceParameter).FullName);
44 : }
45 :
46 : /// <summary>
47 : /// The <see cref="IServiceParameterResolver"/> that has information about resolving authentication tokens such as <typeparamref name="TAuthenticationToken"/>.
48 : /// </summary>
49 : protected IServiceParameterResolver TokenResolver { get; private set; }
50 :
51 : /// <summary>
52 : /// Gets or sets the <see cref="IEventDataResolver"/>.
53 : /// </summary>
54 : protected IEventDataResolver EventDataResolver { get; private set; }
55 :
56 : /// <summary>
57 : /// The Service Name included in all <see cref="Type"/> resolution information.
58 : /// </summary>
59 : protected string ServiceNamespace { get; private set; }
60 :
61 : /// <summary>
62 : /// Maps a data contract type to an xsi:type name and namespace during serialization.
63 : /// </summary>
64 : /// <param name="dataContractType">The type to map.</param>
65 : /// <param name="declaredType">The type declared in the data contract.</param>
66 : /// <param name="knownTypeResolver">The known type resolver.</param>
67 : /// <param name="typeName">The xsi:type name.</param>
68 : /// <param name="typeNamespace">The xsi:type namespace.</param>
69 : /// <returns>true if mapping succeeded; otherwise, false.</returns>
70 1 : public override bool TryResolveType(Type dataContractType, Type declaredType, DataContractResolver knownTypeResolver, out XmlDictionaryString typeName, out XmlDictionaryString typeNamespace)
71 : {
72 : if (dataContractType == typeof(ServiceResponse))
73 : {
74 : XmlDictionary dictionary = new XmlDictionary();
75 : typeName = dictionary.Add("ServiceResponse");
76 : typeNamespace = dictionary.Add(ServiceNamespace);
77 : return true;
78 : }
79 :
80 : if (dataContractType == typeof(ServiceRequest<TAuthenticationToken>))
81 : {
82 : XmlDictionary dictionary = new XmlDictionary();
83 : typeName = dictionary.Add("ServiceRequest");
84 : typeNamespace = dictionary.Add(ServiceNamespace);
85 : return true;
86 : }
87 :
88 : bool result = TokenResolver.TryResolveType(dataContractType, declaredType, knownTypeResolver, out typeName, out typeNamespace);
89 : if (result)
90 : return true;
91 :
92 : result = EventDataResolver.TryResolveType(dataContractType, declaredType, knownTypeResolver, out typeName, out typeNamespace);
93 : if (result)
94 : return true;
95 :
96 : result = TryResolveUnResolvedType(dataContractType, declaredType, knownTypeResolver, ref typeName, ref typeNamespace);
97 : if (result)
98 : return true;
99 :
100 : // Defer to the known type resolver
101 : return knownTypeResolver.TryResolveType(dataContractType, declaredType, null, out typeName, out typeNamespace);
102 : }
103 :
104 : /// <summary>
105 : /// Try to resolve an types <see cref="TryResolveType"/> fails to.
106 : /// </summary>
107 : /// <param name="dataContractType">The type to map.</param>
108 : /// <param name="declaredType">The type declared in the data contract.</param>
109 : /// <param name="knownTypeResolver">The known type resolver.</param>
110 : /// <param name="typeName">The xsi:type name.</param>
111 : /// <param name="typeNamespace">The xsi:type namespace.</param>
112 : /// <returns>true if mapping succeeded; otherwise, false.</returns>
113 1 : protected abstract bool TryResolveUnResolvedType(Type dataContractType, Type declaredType, DataContractResolver knownTypeResolver, ref XmlDictionaryString typeName, ref XmlDictionaryString typeNamespace);
114 :
115 : /// <summary>
116 : /// Maps the specified xsi:type name and namespace to a data contract type during deserialization.
117 : /// </summary>
118 : /// <returns>
119 : /// The type the xsi:type name and namespace is mapped to.
120 : /// </returns>
121 : /// <param name="typeName">The xsi:type name to map.</param>
122 : /// <param name="typeNamespace">The xsi:type namespace to map.</param>
123 : /// <param name="declaredType">The type declared in the data contract.</param>
124 : /// <param name="knownTypeResolver">The known type resolver.</param>
125 1 : public override Type ResolveName(string typeName, string typeNamespace, Type declaredType, DataContractResolver knownTypeResolver)
126 : {
127 : if (typeNamespace == ServiceNamespace)
128 : {
129 : if (typeName == "ServiceResponse")
130 : {
131 : return typeof(ServiceResponse);
132 : }
133 :
134 : if (typeName == "ServiceRequest")
135 : {
136 : return typeof(ServiceRequest<TAuthenticationToken>);
137 : }
138 : }
139 :
140 : Type result = TokenResolver.ResolveName(typeName, typeNamespace, declaredType, knownTypeResolver);
141 : if (result != null)
142 : return result;
143 :
144 : result = EventDataResolver.ResolveName(typeName, typeNamespace, declaredType, knownTypeResolver);
145 : if (result != null)
146 : return result;
147 :
148 : result = ResolveUnResolvedName(typeName, typeNamespace, declaredType, knownTypeResolver);
149 : if (result != null)
150 : return result;
151 :
152 : // Defer to the known type resolver
153 : return knownTypeResolver.ResolveName(typeName, typeNamespace, declaredType, null);
154 : }
155 :
156 : /// <summary>
157 : /// Try to resolve an types <see cref="ResolveName"/> fails to.
158 : /// </summary>
159 : /// <returns>
160 : /// The type the xsi:type name and namespace is mapped to.
161 : /// </returns>
162 : /// <param name="typeName">The xsi:type name to map.</param>
163 : /// <param name="typeNamespace">The xsi:type namespace to map.</param>
164 : /// <param name="declaredType">The type declared in the data contract.</param>
165 : /// <param name="knownTypeResolver">The known type resolver.</param>
166 1 : protected abstract Type ResolveUnResolvedName(string typeName, string typeNamespace, Type declaredType, DataContractResolver knownTypeResolver);
167 : }
168 : }
|