public void MultiVersionedMessageTest() {
			var v10 = new MessageDescription(typeof(MultiVersionMessage), new Version(1, 0));
			var v20 = new MessageDescription(typeof(MultiVersionMessage), new Version(2, 0));
			var v25 = new MessageDescription(typeof(MultiVersionMessage), new Version(2, 5));
			var v30 = new MessageDescription(typeof(MultiVersionMessage), new Version(3, 0));

			// Verify that the AllVersion member appears in every version.
			Assert.IsTrue(v10.Mapping.ContainsKey("AllVersion"));
			Assert.IsTrue(v20.Mapping.ContainsKey("AllVersion"));
			Assert.IsTrue(v25.Mapping.ContainsKey("AllVersion"));
			Assert.IsTrue(v30.Mapping.ContainsKey("AllVersion"));

			// Verify that UpThru25 disappears in 3.0.
			Assert.IsTrue(v10.Mapping.ContainsKey("UpThru25"));
			Assert.IsTrue(v20.Mapping.ContainsKey("UpThru25"));
			Assert.IsTrue(v25.Mapping.ContainsKey("UpThru25"));
			Assert.IsFalse(v30.Mapping.ContainsKey("UpThru25"));

			// Verify that NewIn20 doesn't appear before that version.
			Assert.IsFalse(v10.Mapping.ContainsKey("NewIn20"));
			Assert.IsTrue(v20.Mapping.ContainsKey("NewIn20"));
			Assert.IsTrue(v25.Mapping.ContainsKey("NewIn20"));
			Assert.IsTrue(v30.Mapping.ContainsKey("NewIn20"));

			// Verify that an optional field in 1.0 becomes required in 2.0
			Assert.IsTrue(v10.Mapping.ContainsKey("RequiredIn20"));
			Assert.IsFalse(v10.Mapping["RequiredIn20"].IsRequired);
			Assert.IsTrue(v20.Mapping.ContainsKey("RequiredIn20"));
			Assert.IsTrue(v20.Mapping["RequiredIn20"].IsRequired);
			Assert.IsTrue(v25.Mapping.ContainsKey("RequiredIn20"));
			Assert.IsTrue(v25.Mapping["RequiredIn20"].IsRequired);
			Assert.IsTrue(v30.Mapping.ContainsKey("RequiredIn20"));
			Assert.IsTrue(v30.Mapping["RequiredIn20"].IsRequired);

			// Verify that one (odd) field appeared in 1.0 as optional,
			// disappeared in 2.0, and then reappeared in 2.5 and later as required.
			Assert.IsTrue(v10.Mapping.ContainsKey("OptionalIn10RequiredIn25AndLater"));
			Assert.IsFalse(v10.Mapping["OptionalIn10RequiredIn25AndLater"].IsRequired);
			Assert.IsFalse(v20.Mapping.ContainsKey("OptionalIn10RequiredIn25AndLater"));
			Assert.IsTrue(v25.Mapping.ContainsKey("OptionalIn10RequiredIn25AndLater"));
			Assert.IsTrue(v25.Mapping["OptionalIn10RequiredIn25AndLater"].IsRequired);
			Assert.IsTrue(v30.Mapping.ContainsKey("OptionalIn10RequiredIn25AndLater"));
			Assert.IsTrue(v30.Mapping["OptionalIn10RequiredIn25AndLater"].IsRequired);
		}
		internal MessageDescription Get(Type messageType, Version messageVersion) {
			Contract.Requires<ArgumentNullException>(messageType != null);
			Contract.Requires<ArgumentException>(typeof(IMessage).IsAssignableFrom(messageType));
			Contract.Requires<ArgumentNullException>(messageVersion != null);
			Contract.Ensures(Contract.Result<MessageDescription>() != null);

			MessageTypeAndVersion key = new MessageTypeAndVersion(messageType, messageVersion);

			MessageDescription result;
			if (!this.reflectedMessageTypes.TryGetValue(key, out result)) {
				lock (this.reflectedMessageTypes) {
					if (!this.reflectedMessageTypes.TryGetValue(key, out result)) {
						this.reflectedMessageTypes[key] = result = new MessageDescription(messageType, messageVersion);
					}
				}
			}

			Contract.Assume(result != null, "We should never assign null values to this dictionary.");
			return result;
		}
		public void CtorsCache() {
			var message = new MessageDescription(typeof(MultiVersionMessage), new Version(1, 0));
			Assert.IsNotNull(message.Constructors);
			Assert.AreEqual(1, message.Constructors.Length);
		}
		public void MessagePartConvertibility() {
			var message = new MessageWithIdentifier();
			var messageDescription = new MessageDescription(message.GetType(), new Version(1, 0));
			var messageDictionary = new MessageDictionary(message, messageDescription, false);
			messageDictionary["Identifier"] = OpenId.OpenIdTestBase.IdentifierSelect;
			Assert.That(messageDictionary["Identifier"], Is.EqualTo(OpenId.OpenIdTestBase.IdentifierSelect));
		}
		/// <summary>
		/// Finds constructors for response messages that take a given request message type.
		/// </summary>
		/// <param name="messageDescription">The message description.</param>
		/// <param name="requestType">Type of the request message.</param>
		/// <returns>A sequence of matching constructors.</returns>
		private IEnumerable<ConstructorInfo> FindMatchingResponseConstructors(MessageDescription messageDescription, Type requestType) {
			Contract.Requires<ArgumentNullException>(messageDescription != null);
			Contract.Requires<ArgumentNullException>(requestType != null);

			return this.responseMessageTypes[messageDescription].Where(pair => pair.Key.IsAssignableFrom(requestType)).Select(pair => pair.Value);
		}
		/// <summary>
		/// Instantiates the given request message type.
		/// </summary>
		/// <param name="messageDescription">The message description.</param>
		/// <param name="request">The request that resulted in this response.</param>
		/// <returns>The instantiated message.  Never null.</returns>
		protected virtual IDirectResponseProtocolMessage InstantiateAsResponse(MessageDescription messageDescription, IDirectedProtocolMessage request) {
			Contract.Requires<ArgumentNullException>(messageDescription != null);
			Contract.Requires<ArgumentNullException>(request != null);
			Contract.Ensures(Contract.Result<IDirectResponseProtocolMessage>() != null);

			Type requestType = request.GetType();
			var ctors = this.FindMatchingResponseConstructors(messageDescription, requestType);
			ConstructorInfo ctor = null;
			try {
				ctor = ctors.Single();
			} catch (InvalidOperationException) {
				if (ctors.Any()) {
					ErrorUtilities.ThrowInternal("More than one matching constructor for request type " + requestType.Name + " and response type " + messageDescription.MessageType.Name);
				} else {
					ErrorUtilities.ThrowInternal("Unexpected request message type " + requestType.FullName + " for response type " + messageDescription.MessageType.Name);
				}
			}
			return (IDirectResponseProtocolMessage)ctor.Invoke(new object[] { request });
		}
		/// <summary>
		/// Instantiates the given request message type.
		/// </summary>
		/// <param name="messageDescription">The message description.</param>
		/// <param name="recipient">The recipient.</param>
		/// <returns>The instantiated message.  Never null.</returns>
		protected virtual IDirectedProtocolMessage InstantiateAsRequest(MessageDescription messageDescription, MessageReceivingEndpoint recipient) {
			Contract.Requires<ArgumentNullException>(messageDescription != null);
			Contract.Requires<ArgumentNullException>(recipient != null);
			Contract.Ensures(Contract.Result<IDirectedProtocolMessage>() != null);

			ConstructorInfo ctor = this.requestMessageTypes[messageDescription];
			return (IDirectedProtocolMessage)ctor.Invoke(new object[] { recipient.Location, messageDescription.MessageVersion });
		}
Example #8
0
		public void MessagePartConvertibility() {
			var message = new MessageWithRealm();
			var messageDescription = new MessageDescription(message.GetType(), new Version(1, 0));
			var messageDictionary = new MessageDictionary(message, messageDescription, false);
			messageDictionary["Realm"] = OpenId.OpenIdTestBase.RPRealmUri.AbsoluteUri;
			Assert.That(messageDictionary["Realm"], Is.EqualTo(OpenId.OpenIdTestBase.RPRealmUri.AbsoluteUri));
		}
		/// <summary>
		/// Finds constructors for response messages that take a given request message type.
		/// </summary>
		/// <param name="messageDescription">The message description.</param>
		/// <param name="requestType">Type of the request message.</param>
		/// <returns>A sequence of matching constructors.</returns>
		private IEnumerable<ConstructorInfo> FindMatchingResponseConstructors(MessageDescription messageDescription, Type requestType) {
			Requires.NotNull(messageDescription, "messageDescription");
			Requires.NotNull(requestType, "requestType");

			return this.responseMessageTypes[messageDescription].Where(pair => pair.Key.IsAssignableFrom(requestType)).Select(pair => pair.Value);
		}
		/// <summary>
		/// Instantiates the given request message type.
		/// </summary>
		/// <param name="messageDescription">The message description.</param>
		/// <param name="recipient">The recipient.</param>
		/// <returns>The instantiated message.  Never null.</returns>
		protected virtual IDirectedProtocolMessage InstantiateAsRequest(MessageDescription messageDescription, MessageReceivingEndpoint recipient) {
			Requires.NotNull(messageDescription, "messageDescription");
			Requires.NotNull(recipient, "recipient");

			ConstructorInfo ctor = this.requestMessageTypes[messageDescription];
			return (IDirectedProtocolMessage)ctor.Invoke(new object[] { recipient.Location, messageDescription.MessageVersion });
		}