Permalink
Browse files

Added ExpressionToCode library for unit test expression-based asserts.

Added Xml(De)Serializers based on .Net framework XmlSerializer.
Updated Subscriber and SubscriberList entity definitions to use Xml attributes rather than the RestSharp attributes.
Added dedicated Deserialization unit tests for SubscriberList.
  • Loading branch information...
1 parent 2778b92 commit 3edf806f1f1bc2cde58f12da7815ac63268b8965 dan committed Sep 8, 2011
@@ -4,6 +4,7 @@
using System.Net;
using RestSharp;
using System.Linq;
+ using Xml;
public class SpreedlyClient: ISpreedlyClient
{
@@ -93,6 +94,10 @@ private RestClient GetClient()
{
var client = new RestClient(BaseSpreedlyUrl);
client.Authenticator = new HttpBasicAuthenticator(_userName, _password);
+ client.RemoveHandler("application/xml");
+ client.RemoveHandler("text/xml");
+ client.AddHandler("application/xml", new FrameworkDeserializer());
+ client.AddHandler("text/xml", new FrameworkDeserializer());
return client;
}
@@ -1,75 +1,113 @@
namespace Spreedly.Net.Entities
{
using System;
- using RestSharp.Serializers;
+ using System.Xml.Serialization;
+ using Xml;
- [SerializeAs(NameStyle = NameStyle.LowerCase)]
+ [XmlRoot(ElementName = "subscriber")]
public class Subscriber
{
- public bool? Active { get; set; }
- [SerializeAs(Name = "active-until")]
- public DateTime? ActiveUntil { get; set; }
- [SerializeAs(Name = "billing-first-name")]
+ [XmlElement(ElementName = "active", IsNullable = true)]
+ public SerializableNullable<bool> Active { get; set; }
+
+ [XmlElement(ElementName = "active-until", IsNullable = true)]
+ public SerializableNullable<DateTime> ActiveUntil { get; set; }
+
+ [XmlElement(ElementName = "billing-first-name")]
public string BillingFirstName { get; set; }
- [SerializeAs(Name = "billing-last-name")]
+
+ [XmlElement(ElementName = "billing-last-name")]
public string BillingLastName { get; set; }
- [SerializeAs(Name = "card-expires-before-next-auto-renew")]
- public bool? CardExpiresBeforeNextAutoRenew { get; set; }
- [SerializeAs(Name = "created-at")]
- public DateTime? CreatedAt { get; set; }
- [SerializeAs(Name = "customer-id")]
+
+ [XmlElement(ElementName = "card-expires-before-next-auto-renew", IsNullable = true)]
+ public SerializableNullable<bool> CardExpiresBeforeNextAutoRenew { get; set; }
+
+ [XmlElement(ElementName = "created-at", IsNullable = true)]
+ public SerializableNullable<DateTime> CreatedAt { get; set; }
+
+ [XmlElement(ElementName = "customer-id")]
public string CustomerId { get; set; }
- [SerializeAs(Name = "eligible-for-free-trial")]
- public bool? EligibleForFreeTrial { get; set; }
+
+ [XmlElement(ElementName = "eligible-for-free-trial", IsNullable = true)]
+ public SerializableNullable<bool> EligibleForFreeTrial { get; set; }
+
+ [XmlElement(ElementName = "email")]
public string Email { get; set; }
- [SerializeAs(Name = "feature-level")]
+
+ [XmlElement(ElementName = "feature-level")]
public string FeatureLevel { get; set; }
- [SerializeAs(Name = "lifetime-subscription")]
- public bool? LifetimeSubscription { get; set; }
- [SerializeAs(Name = "on-trial")]
- public bool? OnTrial { get; set; }
- [SerializeAs(Name = "on-gift")]
- public bool? OnGift { get; set; }
- [SerializeAs(Name = "on-metered")]
- public bool? OnMetered { get; set; }
- public bool? Recurring { get; set; }
- [SerializeAs(Name = "screen-name")]
+
+ [XmlElement(ElementName = "lifetime-subscription", IsNullable = true)]
+ public SerializableNullable<bool> LifetimeSubscription { get; set; }
+
+ [XmlElement(ElementName = "on-trial", IsNullable = true)]
+ public SerializableNullable<bool> OnTrial { get; set; }
+
+ [XmlElement(ElementName = "on-gift", IsNullable = true)]
+ public SerializableNullable<bool> OnGift { get; set; }
+
+ [XmlElement(ElementName = "on-metered")]
+ public SerializableNullable<bool> OnMetered { get; set; }
+
+ [XmlElement(ElementName = "recurring", IsNullable = true)]
+ public SerializableNullable<bool> Recurring { get; set; }
+
+ [XmlElement(ElementName = "screen-name")]
public string ScreenName { get; set; }
- [SerializeAs(Name = "store-credit")]
- public decimal? StoreCredit { get; set; }
- [SerializeAs(Name = "store-credit-currency-code")]
+
+ [XmlElement(ElementName = "store-credit")]
+ public SerializableNullable<decimal> StoreCredit { get; set; }
+
+ [XmlElement(ElementName = "store-credit-currency-code")]
public string StoreCreditCurrencyCode { get; set; }
- [SerializeAs(Name = "subscription-plan-name")]
+
+ [XmlElement(ElementName = "subscription-plan-name")]
public string SubscriptionPlanName { get; set; }
+
+ [XmlElement(ElementName = "token")]
public string Token { get; set; }
- [SerializeAs(Name = "updated-at")]
- public DateTime? UpdatedAt { get; set; }
- [SerializeAs(Name = "grace-until")]
- public DateTime? GraceUntil { get; set; }
- [SerializeAs(Name = "in-grace-period")]
- public bool? InGracePeriod { get; set; }
- [SerializeAs(Name = "ready-to-renew")]
- public bool? ReadyToRenew { get; set; }
- [SerializeAs(Name = "ready-to-renew-since")]
- public DateTime? ReadyToRenewSince { get; set; }
- [SerializeAs(Name = "payment-account-on-file")]
- public bool? PaymentAccountOnFile { get; set; }
- [SerializeAs(Name = "payment-account-display")]
- public bool? PaymentAccountDisplay { get; set; }
- [SerializeAs(Name = "billing-address1")]
+
+ [XmlElement(ElementName = "updated-at", IsNullable = true)]
+ public SerializableNullable<DateTime> UpdatedAt { get; set; }
+
+ [XmlElement(ElementName = "grace-until", IsNullable = true)]
+ public SerializableNullable<DateTime> GraceUntil { get; set; }
+
+ [XmlElement(ElementName = "in-grace-period", IsNullable = true)]
+ public SerializableNullable<bool> InGracePeriod { get; set; }
+
+ [XmlElement(ElementName = "ready-to-renew", IsNullable = true)]
+ public SerializableNullable<bool> ReadyToRenew { get; set; }
+
+ [XmlElement(ElementName = "ready-to-renew-since", IsNullable = true)]
+ public SerializableNullable<DateTime> ReadyToRenewSince { get; set; }
+
+ [XmlElement(ElementName = "payment-account-on-file", IsNullable = true)]
+ public SerializableNullable<bool> PaymentAccountOnFile { get; set; }
+
+ [XmlElement(ElementName = "payment-account-display", IsNullable = true)]
+ public string PaymentAccountDisplay { get; set; }
+
+ [XmlElement(ElementName = "billing-address1")]
public string BillingAddress1 { get; set; }
- [SerializeAs(Name = "billing-city")]
+
+ [XmlElement(ElementName = "billing-city")]
public string BillingCity { get; set; }
- [SerializeAs(Name = "billing-state")]
+
+ [XmlElement(ElementName = "billing-state")]
public string BillingState { get; set; }
- [SerializeAs(Name = "billing-zip")]
+
+ [XmlElement(ElementName = "billing-zip")]
public string BillingZip { get; set; }
- [SerializeAs(Name = "billing-country")]
+
+ [XmlElement(ElementName = "billing-country")]
public string BillingCountry { get; set; }
- [SerializeAs(Name = "billing-phone-number")]
+
+ [XmlElement(ElementName = "billing-phone-number")]
public string BillingPhoneNumber { get; set; }
- [SerializeAs(Name = "payment-method")]
+
+ [XmlElement(ElementName = "payment-method")]
public CreditCard PaymentMethod { get; set; }
}
}
@@ -1,9 +1,12 @@
namespace Spreedly.Net.Entities
{
using System.Collections.Generic;
-
+ using System.Xml.Serialization;
+
+ [XmlRoot(ElementName = "subscribers")]
public class SubscriberList
{
+ [XmlElement(ElementName = "subscriber")]
public List<Subscriber> Subscribers { get; set; }
public SubscriberList()
@@ -68,6 +68,9 @@
<Compile Include="Entities\SubscriptionPlan.cs" />
<Compile Include="Entities\SubscriptionPlanList.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="Xml\FrameworkDeserializer.cs" />
+ <Compile Include="Xml\FrameworkSerializer.cs" />
+ <Compile Include="Xml\SerializableNullable.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
@@ -0,0 +1,31 @@
+namespace Spreedly.Net.Xml
+{
+ using System.IO;
+ using System.Xml;
+ using System.Xml.Serialization;
+ using RestSharp;
+ using RestSharp.Deserializers;
+
+ public class FrameworkDeserializer: IDeserializer
+ {
+ public T Deserialize<T>(RestResponse response) where T : new()
+ {
+ if (response == null || response.Content == null)
+ return default(T);
+
+ XmlDocument doc;
+ return Deserialize<T>(XmlReader.Create(new StringReader(response.Content)));
+ }
+
+ private T Deserialize<T>(XmlReader contentReader)
+ {
+ var serializer = new XmlSerializer(typeof (T));
+ return (T)serializer.Deserialize(contentReader);
+ }
+
+ public string RootElement { get; set; }
+ public string Namespace { get; set; }
+ public string DateFormat { get; set; }
+ }
+
+}
@@ -0,0 +1,46 @@
+namespace Spreedly.Net.Xml
+{
+ using System.IO;
+ using System.Text;
+ using System.Xml.Serialization;
+ using RestSharp.Serializers;
+
+ public class FrameworkSerializer: ISerializer
+ {
+ public string Serialize(object obj)
+ {
+ var ns = new XmlSerializerNamespaces();
+ ns.Add(string.Empty, this.Namespace);
+ var serializer = new System.Xml.Serialization.XmlSerializer(obj.GetType());
+ var writer = new EncodingStringWriter(this.Encoding);
+ serializer.Serialize(writer, obj, ns);
+
+ return writer.ToString();
+ }
+
+ public Encoding Encoding { get; set; }
+ public string RootElement { get; set; }
+ public string Namespace { get; set; }
+ public string DateFormat { get; set; }
+ public string ContentType { get; set; }
+
+
+ private class EncodingStringWriter : StringWriter
+ {
+ private readonly Encoding encoding;
+
+ public EncodingStringWriter(Encoding encoding)
+ {
+ this.encoding = encoding;
+ }
+
+ public override Encoding Encoding
+ {
+ get
+ {
+ return this.encoding;
+ }
+ }
+ }
+ }
+}
@@ -0,0 +1,88 @@
+namespace Spreedly.Net.Xml
+{
+ using System;
+ using System.ComponentModel;
+ using System.Xml;
+ using System.Xml.Schema;
+ using System.Xml.Serialization;
+
+ public struct SerializableNullable<T> : IXmlSerializable, IEquatable<SerializableNullable<T>> where T : struct
+ {
+ private T value;
+ private bool hasValue;
+
+ private SerializableNullable(T value)
+ {
+ hasValue = true;
+ this.value = value;
+ }
+
+ public bool HasValue
+ {
+ get { return hasValue; }
+ }
+
+ public T Value
+ {
+ get { return value; }
+ }
+
+ XmlSchema IXmlSerializable.GetSchema()
+ {
+ return null;
+ }
+
+ void IXmlSerializable.ReadXml(XmlReader reader)
+ {
+ if (reader.GetAttribute("nil") == "true")
+ {
+ ReadNullValue();
+ return;
+ }
+ ReadNonNullValue(reader);
+ }
+
+ void IXmlSerializable.WriteXml(XmlWriter writer)
+ {
+ if(HasValue)
+ writer.WriteValue(value);
+ else
+ {
+ writer.WriteAttributeString("nil", string.Empty, "true");
+ writer.WriteValue(string.Empty);
+ }
+ }
+
+ private void ReadNullValue()
+ {
+ hasValue = false;
+ }
+
+ private void ReadNonNullValue(XmlReader reader)
+ {
+ reader.ReadStartElement();
+ var s = reader.ReadString();
+ value = GetValue(s);
+ reader.ReadEndElement();
+ hasValue = true;
+ }
+
+ private T GetValue(string readValue)
+ {
+ var descriptor = TypeDescriptor.GetConverter(typeof (T));
+ if (descriptor.CanConvertFrom(typeof(string)))
+ return (T)descriptor.ConvertFromInvariantString(readValue);
+ return default(T);
+ }
+
+ public static implicit operator SerializableNullable<T>(T value)
+ {
+ return new SerializableNullable<T>(value);
+ }
+
+ public bool Equals(SerializableNullable<T> other)
+ {
+ return HasValue == other.HasValue && Value.Equals(other.Value);
+ }
+ }
+}
Oops, something went wrong.

0 comments on commit 3edf806

Please sign in to comment.