Skip to content

Commit

Permalink
Added ExpressionToCode library for unit test expression-based asserts.
Browse files Browse the repository at this point in the history
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
dan committed Sep 8, 2011
1 parent 2778b92 commit 3edf806
Show file tree
Hide file tree
Showing 11 changed files with 371 additions and 52 deletions.
5 changes: 5 additions & 0 deletions Spreedly.Net/Client/SpreedlyClient.cs
Expand Up @@ -4,6 +4,7 @@
using System.Net; using System.Net;
using RestSharp; using RestSharp;
using System.Linq; using System.Linq;
using Xml;


public class SpreedlyClient: ISpreedlyClient public class SpreedlyClient: ISpreedlyClient
{ {
Expand Down Expand Up @@ -93,6 +94,10 @@ private RestClient GetClient()
{ {
var client = new RestClient(BaseSpreedlyUrl); var client = new RestClient(BaseSpreedlyUrl);
client.Authenticator = new HttpBasicAuthenticator(_userName, _password); 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; return client;
} }


Expand Down
138 changes: 88 additions & 50 deletions Spreedly.Net/Entities/Subscriber.cs
@@ -1,75 +1,113 @@
namespace Spreedly.Net.Entities namespace Spreedly.Net.Entities
{ {
using System; using System;
using RestSharp.Serializers; using System.Xml.Serialization;
using Xml;


[SerializeAs(NameStyle = NameStyle.LowerCase)] [XmlRoot(ElementName = "subscriber")]
public class Subscriber public class Subscriber
{ {


public bool? Active { get; set; } [XmlElement(ElementName = "active", IsNullable = true)]
[SerializeAs(Name = "active-until")] public SerializableNullable<bool> Active { get; set; }
public DateTime? ActiveUntil { get; set; }
[SerializeAs(Name = "billing-first-name")] [XmlElement(ElementName = "active-until", IsNullable = true)]
public SerializableNullable<DateTime> ActiveUntil { get; set; }

[XmlElement(ElementName = "billing-first-name")]
public string BillingFirstName { get; set; } public string BillingFirstName { get; set; }
[SerializeAs(Name = "billing-last-name")]
[XmlElement(ElementName = "billing-last-name")]
public string BillingLastName { get; set; } public string BillingLastName { get; set; }
[SerializeAs(Name = "card-expires-before-next-auto-renew")]
public bool? CardExpiresBeforeNextAutoRenew { get; set; } [XmlElement(ElementName = "card-expires-before-next-auto-renew", IsNullable = true)]
[SerializeAs(Name = "created-at")] public SerializableNullable<bool> CardExpiresBeforeNextAutoRenew { get; set; }
public DateTime? CreatedAt { get; set; }
[SerializeAs(Name = "customer-id")] [XmlElement(ElementName = "created-at", IsNullable = true)]
public SerializableNullable<DateTime> CreatedAt { get; set; }

[XmlElement(ElementName = "customer-id")]
public string CustomerId { get; set; } 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; } public string Email { get; set; }
[SerializeAs(Name = "feature-level")]
[XmlElement(ElementName = "feature-level")]
public string FeatureLevel { get; set; } public string FeatureLevel { get; set; }
[SerializeAs(Name = "lifetime-subscription")]
public bool? LifetimeSubscription { get; set; } [XmlElement(ElementName = "lifetime-subscription", IsNullable = true)]
[SerializeAs(Name = "on-trial")] public SerializableNullable<bool> LifetimeSubscription { get; set; }
public bool? OnTrial { get; set; }
[SerializeAs(Name = "on-gift")] [XmlElement(ElementName = "on-trial", IsNullable = true)]
public bool? OnGift { get; set; } public SerializableNullable<bool> OnTrial { get; set; }
[SerializeAs(Name = "on-metered")]
public bool? OnMetered { get; set; } [XmlElement(ElementName = "on-gift", IsNullable = true)]
public bool? Recurring { get; set; } public SerializableNullable<bool> OnGift { get; set; }
[SerializeAs(Name = "screen-name")]
[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; } public string ScreenName { get; set; }
[SerializeAs(Name = "store-credit")]
public decimal? StoreCredit { get; set; } [XmlElement(ElementName = "store-credit")]
[SerializeAs(Name = "store-credit-currency-code")] public SerializableNullable<decimal> StoreCredit { get; set; }

[XmlElement(ElementName = "store-credit-currency-code")]
public string StoreCreditCurrencyCode { get; set; } public string StoreCreditCurrencyCode { get; set; }
[SerializeAs(Name = "subscription-plan-name")]
[XmlElement(ElementName = "subscription-plan-name")]
public string SubscriptionPlanName { get; set; } public string SubscriptionPlanName { get; set; }

[XmlElement(ElementName = "token")]
public string Token { get; set; } public string Token { get; set; }
[SerializeAs(Name = "updated-at")]
public DateTime? UpdatedAt { get; set; } [XmlElement(ElementName = "updated-at", IsNullable = true)]
[SerializeAs(Name = "grace-until")] public SerializableNullable<DateTime> UpdatedAt { get; set; }
public DateTime? GraceUntil { get; set; }
[SerializeAs(Name = "in-grace-period")] [XmlElement(ElementName = "grace-until", IsNullable = true)]
public bool? InGracePeriod { get; set; } public SerializableNullable<DateTime> GraceUntil { get; set; }
[SerializeAs(Name = "ready-to-renew")]
public bool? ReadyToRenew { get; set; } [XmlElement(ElementName = "in-grace-period", IsNullable = true)]
[SerializeAs(Name = "ready-to-renew-since")] public SerializableNullable<bool> InGracePeriod { get; set; }
public DateTime? ReadyToRenewSince { get; set; }
[SerializeAs(Name = "payment-account-on-file")] [XmlElement(ElementName = "ready-to-renew", IsNullable = true)]
public bool? PaymentAccountOnFile { get; set; } public SerializableNullable<bool> ReadyToRenew { get; set; }
[SerializeAs(Name = "payment-account-display")]
public bool? PaymentAccountDisplay { get; set; } [XmlElement(ElementName = "ready-to-renew-since", IsNullable = true)]
[SerializeAs(Name = "billing-address1")] 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; } public string BillingAddress1 { get; set; }
[SerializeAs(Name = "billing-city")]
[XmlElement(ElementName = "billing-city")]
public string BillingCity { get; set; } public string BillingCity { get; set; }
[SerializeAs(Name = "billing-state")]
[XmlElement(ElementName = "billing-state")]
public string BillingState { get; set; } public string BillingState { get; set; }
[SerializeAs(Name = "billing-zip")]
[XmlElement(ElementName = "billing-zip")]
public string BillingZip { get; set; } public string BillingZip { get; set; }
[SerializeAs(Name = "billing-country")]
[XmlElement(ElementName = "billing-country")]
public string BillingCountry { get; set; } public string BillingCountry { get; set; }
[SerializeAs(Name = "billing-phone-number")]
[XmlElement(ElementName = "billing-phone-number")]
public string BillingPhoneNumber { get; set; } public string BillingPhoneNumber { get; set; }
[SerializeAs(Name = "payment-method")]
[XmlElement(ElementName = "payment-method")]
public CreditCard PaymentMethod { get; set; } public CreditCard PaymentMethod { get; set; }
} }
} }
5 changes: 4 additions & 1 deletion Spreedly.Net/Entities/SubscriberList.cs
@@ -1,9 +1,12 @@
namespace Spreedly.Net.Entities namespace Spreedly.Net.Entities
{ {
using System.Collections.Generic; using System.Collections.Generic;

using System.Xml.Serialization;

[XmlRoot(ElementName = "subscribers")]
public class SubscriberList public class SubscriberList
{ {
[XmlElement(ElementName = "subscriber")]
public List<Subscriber> Subscribers { get; set; } public List<Subscriber> Subscribers { get; set; }


public SubscriberList() public SubscriberList()
Expand Down
3 changes: 3 additions & 0 deletions Spreedly.Net/Spreedly.Net.csproj
Expand Up @@ -68,6 +68,9 @@
<Compile Include="Entities\SubscriptionPlan.cs" /> <Compile Include="Entities\SubscriptionPlan.cs" />
<Compile Include="Entities\SubscriptionPlanList.cs" /> <Compile Include="Entities\SubscriptionPlanList.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Xml\FrameworkDeserializer.cs" />
<Compile Include="Xml\FrameworkSerializer.cs" />
<Compile Include="Xml\SerializableNullable.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="packages.config" /> <None Include="packages.config" />
Expand Down
31 changes: 31 additions & 0 deletions Spreedly.Net/Xml/FrameworkDeserializer.cs
@@ -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; }
}

}
46 changes: 46 additions & 0 deletions Spreedly.Net/Xml/FrameworkSerializer.cs
@@ -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;
}
}
}
}
}
88 changes: 88 additions & 0 deletions Spreedly.Net/Xml/SerializableNullable.cs
@@ -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);
}
}
}

0 comments on commit 3edf806

Please sign in to comment.