<file_sep>﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Nextension.Annotations;

namespace Nextension
{
	/// <summary>
	/// The utilities for <see cref="Object"/>'s overriding method.
	/// </summary>
	public static class Overrides
	{
		private const Int32 HashCodeSeed = 17;

		private const Int32 HashCodeStep = 23;

		/// <summary>
		/// Calculates the passing objects' hashcode.
		/// This is also a convenient implement for the overrided <see cref="Object.GetHashCode"/>.
		/// </summary>
		/// <param name="objs">The objects to be caculating.</param>
		/// <returns>The hash code of the set of <paramref name="objs"/>.</returns>
		public static Int32 CalculateHashCode(params Object[] objs)
		{
			return CalculateHashCode(objs as IEnumerable);
		}

		/// <summary>
		/// Calculates the passing objects' hashcode.
		/// </summary>
		/// <param name="objs">The objects to be caculating.</param>
		/// <returns>The hash code of the set of <paramref name="objs"/>.</returns>
		public static Int32 CalculateHashCode(IEnumerable objs)
		{
			// Overflow is fine, just wrap
			unchecked
			{
				return objs
					.Cast<Object>()
					.Where(obj => obj != null)
					.Aggregate(HashCodeSeed, (current, obj) => (current * HashCodeStep) + obj.GetHashCode());
			}
		}

		/// <summary>
		/// Comparer equality between <paramref name="source"/> and <paramref name="other"/>.
		/// This is also a convenient implement for the overrided <see cref="IEqualityComparer{T}.Equals(T,T)"/>.
		/// </summary>
		/// <param name="source">The source object.</param>
		/// <param name="other">The other object.</param>
		/// <param name="selectors">The selector to select the value to compare.</param>
		public static Boolean EqualsWith<T>([CanBeNull] this T source, [CanBeNull] T other, params Func<T, Object>[] selectors)
		{
			Ensure.ArgumentNotNull(selectors, "selectors");

			return ReferenceEquals(source, other) || (source != null && other != null && selectors.Length != 0 && selectors.All(s => Equals(s(source), s(other))));
		}

		/// <summary>
		/// Comparer equality between <paramref name="source"/> and <paramref name="other"/>.
		/// This is also a convenient implement for the overrided <see cref="Object.Equals(Object)"/>.
		/// </summary>
		/// <param name="source">The source object.</param>
		/// <param name="other">The other object.</param>
		/// <param name="selectors">The selector to select the value to compare.</param>
		public static Boolean EqualsWith<T>([CanBeNull] this T source, [CanBeNull] Object other, params Func<T, Object>[] selectors)
		{
			Ensure.ArgumentNotNull(selectors, "selectors");

			if (ReferenceEquals(source, other))
			{
				return true;
			}

			T castedOther;
			return other.TryCast(out castedOther) && source.EqualsWith(castedOther, selectors);
		}
	}
}
<file_sep>﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

namespace Nextension
{
	static class Helpers
	{
		public static readonly IEnumerable NonGenericNullEnumerable = null;

		public static readonly IEnumerable NonGenericEmptyEnumerable = new Object[0];

		public static IEnumerable NonGenericBlankEnumerable(Int32 length = 1)
		{
			return new Object[length];
		}

		public static IEnumerable<T> GenericNullEnumerable<T>()
		{
			return null;
		}

		public static IEnumerable<T> GenericEmptyEnumerable<T>()
		{
			return Enumerable.Empty<T>();
		}

		public static IEnumerable<T> GenericBlankEnumerable<T>(Int32 length = 1)
			where T : class
		{
			return Enumerable.Repeat<T>(null, length);
		}

		public static readonly String NullString = null;

		public static readonly String EmptyString = String.Empty;
	}
}
<file_sep>﻿using System;
using Xunit;

namespace Nextension
{
	public class ObjectExtensionsTests
	{
		[Fact]
		public void ValueOrDefault()
		{
			Assert.Null(((String)null).ValueOrDefault(x => x.ToString()));
			Assert.Equal(0, ((String)null).ValueOrDefault(x => x.As<IConvertible>().ToInt32(null)));
			Assert.Equal(String.Empty, String.Empty.ValueOrDefault(x => x.ToString()));
			Assert.Equal("foo", "foo".ValueOrDefault(x => x.ToString()));

			Assert.Equal("foo", ((String)null).ValueOrDefault(x => x.ToString(), "foo"));
			Assert.Equal(13, ((String)null).ValueOrDefault(x => x.As<IConvertible>().ToInt32(null), 13));
			Assert.Equal(String.Empty, String.Empty.ValueOrDefault(x => x.ToString(), "foo"));
			Assert.Equal("foo", "foo".ValueOrDefault(x => x.ToString(), "bar"));

			Assert.Equal("foo", ((String)null).ValueOrDefault(x => x.ToString(), () => "foo"));
			Assert.Equal(13, ((String)null).ValueOrDefault(x => x.As<IConvertible>().ToInt32(null), () => 13));
			Assert.Equal(String.Empty, String.Empty.ValueOrDefault(x => x.ToString(), () => "foo"));
			Assert.Equal("foo", "foo".ValueOrDefault(x => x.ToString(), () => "bar"));
		}

		[Fact]
		public void InstanceOf()
		{
			Assert.True(0.InstanceOf<Int32>());
			Assert.True(0.InstanceOf<Int32?>());
			Assert.True(0.InstanceOf<Object>());
			Assert.False(0.InstanceOf<Int64>());
		}

		[Fact]
		public void As()
		{
			Assert.Null(0.As<String>());
			Assert.NotNull(0.As<Object>());
		}

		[Fact]
		public void TryCast()
		{
			String value1;
			Assert.True("Foo".TryCast(out value1));
			Assert.Equal("Foo", value1);

			Int32? value2;
			Assert.False("Foo".TryCast(out value2));
			Assert.Null(value2);

			Int32 value3;
			Assert.False("Foo".TryCast(out value3));
			Assert.Equal(0, value3);
		}

		[Fact]
		public void TryConvert()
		{
			Int32 value1;
			Assert.True("1".TryConvert(out value1));
			Assert.Equal(1, value1);

			Int32? value2;
			Assert.False("abc".TryConvert(out value2));
			Assert.Null(value2);
		}

		[Fact]
		public void TryConvertWithException()
		{
			Exception exception;

			Int32 value1;
			Assert.True("1".TryConvert(out value1, out exception));
			Assert.Equal(1, value1);
			Assert.Null(exception);

			Int32? value2;
			Assert.True("1".TryConvert(out value2, out exception));
			Assert.Equal(1, value2);
			Assert.Null(exception);

			Int32 value3;
			Assert.False("abc".TryConvert(out value3, out exception));
			Assert.Equal(0, value3);
			Assert.NotNull(exception);

			Int32? value4;
			Assert.False("abc".TryConvert(out value4, out exception));
			Assert.Null(value4);
			Assert.NotNull(exception);
		}

		[Fact]
		public void CalculateHashCode()
		{
			// Assert no throws.
			Overrides.CalculateHashCode("a", "b", "c");
		}

		[Fact]
		public void EqualsWith()
		{
			var source = new
			{
				Prop1 = "1", 
				Prop2 = 1, 
				Prop3 = (Object)null, 
			};

			var cloned = new
			{
				source.Prop1, 
				source.Prop2, 
				Prop3 = new Object(), 
			};

			Assert.True(source.EqualsWith(source));
			Assert.False(source.EqualsWith(cloned));

			Assert.True(source.EqualsWith(cloned, x => x.Prop1, x => x.Prop2));
			Assert.False(source.EqualsWith(cloned, x => x.Prop1, x => x.Prop2, x => x.Prop3));

			Object unknownSource = source;
			Object unknownCloned = cloned;

			Assert.True(source.EqualsWith(unknownSource));
			Assert.False(source.EqualsWith(unknownCloned));

			Assert.True(source.EqualsWith(unknownCloned, x => x.Prop1, x => x.Prop2));
			Assert.False(source.EqualsWith(unknownCloned, x => x.Prop1, x => x.Prop2, x => x.Prop3));



			Assert.False(source.EqualsWith(String.Empty));
			Assert.False(source.EqualsWith(String.Empty, x => x.Prop1));
		}
	}
}
<file_sep>﻿using System;
using System.Diagnostics;
using System.Text.RegularExpressions;
using Nextension.Annotations;

namespace Nextension
{
	/// <summary>
	/// The extensions for any <see cref="String"/>.
	/// Should NOT use this class directly.
	/// </summary>
	public static class StringExtensions
	{
		/// <summary>
		/// Determines whether the <paramref name="source"/> matches the regular-expression <paramref name="pattern"/>.
		/// </summary>
		/// <param name="source">The <see cref="String"/> to be determined.</param>
		/// <param name="pattern">The regular-expression.</param>
		/// <returns><c>true</c> means match, <c>false</c> otherwise.</returns>
		[DebuggerStepThrough]
		public static Boolean RegexMatch([CanBeNull]this String source, String pattern)
		{
			Ensure.ArgumentNotNull(pattern, "pattern");

			return source != null && Regex.IsMatch(source, pattern);
		}

		/// <summary>
		/// Replaces <paramref name="source"/> with <paramref name="replacement"/> by regular-expression <paramref name="pattern"/>.
		/// </summary>
		/// <param name="source">The <see cref="String"/> to be replaced.</param>
		/// <param name="pattern">The regular-expression pattern.</param>
		/// <param name="replacement">The regular-expression replacement.</param>
		/// <returns>The replaced string.</returns>
		[DebuggerStepThrough]
		public static String RegexReplace([CanBeNull] this String source, String pattern, String replacement)
		{
			Ensure.ArgumentNotNull(pattern, "pattern");

			return source == null ? null : Regex.Replace(source, pattern, replacement);
		}

		/// <summary>
		/// Determines whether the <paramref name="source"/> is null or empty string.
		/// </summary>
		/// <param name="source">The <see cref="String"/> to be determined.</param>
		/// <returns><c>true</c> means string is null or empty, <c>false</c> otherwise.</returns>
		[DebuggerStepThrough]
		public static Boolean IsEmpty([CanBeNull] this String source)
		{
			return String.IsNullOrEmpty(source);
		}

		/// <summary>
		/// Determines whether the <paramref name="source"/> is neither null nor empty string.
		/// </summary>
		/// <param name="source">The <see cref="String"/> to be determined.</param>
		/// <returns><c>true</c> means string is neither null nor empty, <c>false</c> otherwise.</returns>
		[DebuggerStepThrough]
		public static Boolean IsNotEmpty([CanBeNull] this String source)
		{
			return !String.IsNullOrEmpty(source);
		}

		/// <summary>
		/// Determines whether the <paramref name="source"/> is null or whitespace-only string.
		/// </summary>
		/// <param name="source">The <see cref="String"/> to be determined.</param>
		/// <returns><c>true</c> means string is null or whitespace-only, <c>false</c> otherwise.</returns>
		[DebuggerStepThrough]
		public static Boolean IsBlank([CanBeNull] this String source)
		{
			return String.IsNullOrWhiteSpace(source);
		}

		/// <summary>
		/// Determines whether the <paramref name="source"/> is neither null nor whitespace-only string.
		/// </summary>
		/// <param name="source">The <see cref="String"/> to be determined.</param>
		/// <returns><c>true</c> means string is neither null nor whitespace-only, <c>false</c> otherwise.</returns>
		[DebuggerStepThrough]
		public static Boolean IsNotBlank([CanBeNull] this String source)
		{
			return !String.IsNullOrWhiteSpace(source);
		}
	}
}
<file_sep>﻿using System;
using System.Collections;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using Nextension.Annotations;
using Nextension.Properties;

namespace Nextension
{
	/// <summary>
	/// The utility to ensure the given key matches the specified rules.
	/// </summary>
	public static class Ensure
	{
		/// <summary>
		/// Ensure the <paramref name="source"/> is not null.
		/// </summary>
		/// <param name="source">The <see cref="Object"/> to be ensured.</param>
		/// <param name="name">The object's name.</param>
		/// <exception cref="ArgumentNullException"><paramref name="source "/> is null.</exception>
		[DebuggerStepThrough]
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static void ArgumentNotNull(Object source, [InvokerParameterName] String name)
		{
			if (source == null)
			{
				throw new ArgumentNullException(name);
			}
		}

		/// <summary>
		/// Ensure the <paramref name="source"/> is not null.
		/// </summary>
		/// <param name="source">The <see cref="Object"/> to be ensured.</param>
		/// <param name="name">The object's name.</param>
		/// <param name="message">The message of the throwing exception.</param>
		/// <exception cref="ArgumentNullException"><paramref name="source "/> is null.</exception>
		[DebuggerStepThrough]
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static void ArgumentNotNull(Object source, [InvokerParameterName] String name, String message)
		{
			if (source == null)
			{
				throw new ArgumentNullException(message, name);
			}
		}

		/// <summary>
		/// Ensure the <paramref name="source"/> is not null or zero-length.
		/// </summary>
		/// <param name="source">The <see cref="IEnumerable"/> to be ensured.</param>
		/// <param name="name">The object's name.</param>
		/// <exception cref="ArgumentException"><paramref name="source "/> is null or zero-length.</exception>
		[DebuggerStepThrough]
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static void ArgumentNotEmpty(IEnumerable source, [InvokerParameterName] String name)
		{
			if (source.IsEmpty())
			{
				throw new ArgumentException(Resources.ArgumentCannotBeEmpty, name);
			}
		}

		/// <summary>
		/// Ensure the <paramref name="source"/> is not null.
		/// </summary>
		/// <param name="source">The <see cref="IEnumerable"/> to be ensured.</param>
		/// <param name="name">The object's name.</param>
		/// <param name="message">The message of the throwing exception.</param>
		/// <exception cref="ArgumentException"><paramref name="source "/> is null or zero-length.</exception>
		[DebuggerStepThrough]
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static void ArgumentNotEmpty(IEnumerable source, [InvokerParameterName] String name, String message)
		{
			if (source.IsEmpty())
			{
				throw new ArgumentException(message, name);
			}
		}

	}
}<file_sep>﻿using System;
using System.Collections;
using System.Collections.Generic;
using Xunit;

namespace Nextension
{
	public class DictionaryExtensionsTests
	{
		[Fact]
		public void AsSafeDictionary()
		{
			var source = new Dictionary<String, String>();

			var safeDictionary = source.AsSafeDictionary();

			Assert.Empty(source);
			Assert.Empty(safeDictionary);

			source.Add("key", "value");

			Assert.Single(source);
			Assert.Single(safeDictionary);
		}

		[Fact]
		public void ToSafeDictionary_FromDictionary()
		{
			var source = new Dictionary<String, String>
			{
				{"foo", "value"}, 
				{"bar", "value2"}, 
			};

			var safeDictionary = source.ToSafeDictionary();
			var caseInsensitiveSafeDictionary = source.ToSafeDictionary(StringComparer.OrdinalIgnoreCase);

			source.Clear();

			Assert.NotEmpty(safeDictionary);
			Assert.NotEmpty(caseInsensitiveSafeDictionary);

			Assert.True(safeDictionary.ContainsKey("foo"));
			Assert.False(safeDictionary.ContainsKey("Foo"));

			Assert.True(caseInsensitiveSafeDictionary.ContainsKey("foo"));
			Assert.True(caseInsensitiveSafeDictionary.ContainsKey("Foo"));

			// Assert no exception throw.
			var value = safeDictionary["not_exist"];
			Assert.Null(value);
		}

		[Fact]
		public void ToSafeDictionary_WithOrdinalIgnoreCaseComparer_WithDuplicatedKey()
		{
			var source = new Dictionary<String, String>
			{
				{"foo", "value"}, 
				{"Foo", "value2"}, 
			};

			Assert.Throws<ArgumentException>(() => source.ToSafeDictionary(StringComparer.OrdinalIgnoreCase));
		}

		[Fact]
		public void ToSafeDictionary_FromEnumerable()
		{
			String[] source = { "a", "b", "c", "d", "e" };

			var safeDictionaries = new IDictionary<String, String>[4];

			safeDictionaries[0] = source.ToSafeDictionary(i => i);
			safeDictionaries[1] = source.ToSafeDictionary(i => i, StringComparer.OrdinalIgnoreCase);
			safeDictionaries[2] = source.ToSafeDictionary(i => i, i => i.ToUpper());
			safeDictionaries[3] = source.ToSafeDictionary(i => i, i => i.ToUpper(), StringComparer.OrdinalIgnoreCase);

			safeDictionaries.ForEach(x => Assert.Equal(5, x.Count));

			Assert.True(safeDictionaries[0].ContainsKey("a"));
			Assert.False(safeDictionaries[0].ContainsKey("A"));

			Assert.True(safeDictionaries[1].ContainsKey("a"));
			Assert.True(safeDictionaries[1].ContainsKey("A"));

			Assert.Equal("A", safeDictionaries[2]["a"]);
			Assert.Equal(null, safeDictionaries[2]["A"]);

			Assert.Equal("A", safeDictionaries[3]["a"]);
			Assert.Equal("A", safeDictionaries[3]["A"]);
		}

		[Fact]
		public void TryGetValue()
		{
			var source = new Dictionary<String, String>();

			Assert.Null(source.TryGetValue("not_exist"));
			Assert.Null(DictionaryExtensions.TryGetValue<String, String>(null, "what_ever"));

			var source2 = new Dictionary<String, Int32>();
			Assert.Equal(default(Int32), source2.TryGetValue("not_exist"));
			Assert.Equal(default(Int32), DictionaryExtensions.TryGetValue<String, Int32>(null, "what_ever"));
		}

		[Theory]
		[MemberData("TryGetValueChangeableData")]
		public void TryGetValueChangeable(String key, Boolean convert, Boolean expect, Type outputType, Object output)
		{
			var testMethod = new Action<String, Boolean, Boolean, Object>(TryGetValueChangeableInvoker)
				.Method
				.GetGenericMethodDefinition()
				.MakeGenericMethod(outputType);

			testMethod.Invoke(null, new[] { key, convert, expect, output });
		}

		private static void TryGetValueChangeableInvoker<T>(String key, Boolean convert, Boolean expect, T output)
		{
			var source = new Dictionary<String, Object>
			{
				{"string", "value"}, 
				{"int_string", "1"}, 
				{"int", 1}, 
				{"mytype", (Value)"value"}, 
			};

			T value;
			var result = source.TryGetValue(key, out value, convert);

			Assert.Equal(expect, result);
			Assert.Equal(output, value);

			T value2;
			var result2 = ((IDictionary)source).TryGetValue(key, out value2, convert);

			Assert.Equal(expect, result2);
			Assert.Equal(output, value2);
		}

		public static IEnumerable<Object[]> TryGetValueChangeableData()
		{
			// Get value unexist.
			yield return new Object[] { "unexist", false, false, typeof(Object), null };
			yield return new Object[] { "unexist", false, false, typeof(Int32), 0 };
			yield return new Object[] { "unexist", false, false, typeof(Value), null };

			// Get value with down-cast.
			yield return new Object[] { "string", false, true, typeof(String), "value" };
			yield return new Object[] { "int", false, true, typeof(Int32), 1 };
			yield return new Object[] { "mytype", false, true, typeof(Value), (Value)"value" };

			// Get value with cast-operator cast.
			yield return new Object[] { "string", false, false, typeof(Value), null };
			yield return new Object[] { "mytype", false, false, typeof(String), null };

			// Get value with convert.
			yield return new Object[] { "int_string", true, true, typeof(Int32), 1 };
			yield return new Object[] { "int", true, true, typeof(String), "1" };

			// Nullables.
			yield return new Object[] { "unexist", false, false, typeof(Int32?), null };
			yield return new Object[] { "int", false, true, typeof(Int32?), 1 };
			yield return new Object[] { "int_string", true, true, typeof(Int32?), 1 };
			yield return new Object[] { "string", true, false, typeof(Int32?), null };
		}

		private class Value
		{
			private readonly String data;

			private Value(String data)
			{
				this.data = data;
			}

			public static implicit operator String(Value value)
			{
				return value.data;
			}

			public static implicit operator Value(String data)
			{
				return new Value(data);
			}

			public override Boolean Equals(Object obj)
			{
				var that = obj as Value;

				return that != null && this.data.Equals(that.data);
			}

			public override Int32 GetHashCode()
			{
				return this.data.GetHashCode();
			}

			public override String ToString()
			{
				return this.data;
			}
		}
	}
}
<file_sep>﻿using System;
using Xunit;

namespace Nextension
{
	public class EnumExtensionsTests
	{
		private enum Operation
		{
			None = 0,

			Add = 1,

			Minus = 2,

			Mutli = 3,

			Divide = 4,
		}

		[Theory]
		[InlineData(Operation.None, true)]
		[InlineData(Operation.Add, true)]
		[InlineData((Operation)(-1), false)]
		[InlineData(null, false)]
		[InlineData(PlatformID.Unix, true)]
		public void IsDefined(Enum e, Boolean expected)
		{
			Assert.Equal(expected, e.IsDefined());
		}

		[Theory]
		[InlineData(Operation.None, true)]
		[InlineData(Operation.Add, true)]
		[InlineData((Operation)(-1), false)]
		[InlineData(-1, false)]
		[InlineData(null, false)]
		[InlineData(PlatformID.Unix, false)]
		public void IsEnumOfOperation(Object obj, Boolean expected)
		{
			Assert.Equal(expected, obj.IsEnumOf<Operation>());
			Assert.Equal(expected, obj.IsEnumOf(typeof(Operation)));
		}

		[Fact]
		public void IsEnumOfNonEnumType()
		{
			Assert.Throws<ArgumentException>(() => this.IsEnumOf<Int32>());
			Assert.Throws<ArgumentException>(() => Operation.None.IsEnumOf(typeof(Enum)));
		}

		[Fact]
		public void ToUnderlyingType()
		{
			Assert.IsType<Int32>(Operation.None.ToUndelyingType());
			Assert.Null(((Enum)null).ToUndelyingType());
		}

	}
}
<file_sep>﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Nextension.Annotations;

namespace Nextension
{
	/// <summary>
	/// The extensions for any <see cref="IEnumerable{T}"/>.
	/// Should NOT use this class directly.
	/// </summary>
	public static class EnumerableExtensions
	{

		#region Determination

		/// <summary>
		/// Determines whether the <paramref name="source"/> is null or zero-length.
		/// </summary>
		/// <param name="source">The non-generic version <see cref="IEnumerable"/>.</param>
		/// <returns><c>true</c> means empty, <c>false</c> otherwise.</returns>
		[DebuggerStepThrough]
		public static Boolean IsEmpty([CanBeNull] this IEnumerable source)
		{
			var asCollection = source as ICollection;
			if (asCollection != null)
			{
				return asCollection.Count == 0;
			}
			return source == null || !source.GetEnumerator().MoveNext();
		}

		/// <summary>
		/// Determines whether the <paramref name="source"/> is neither null nor zero-length.
		/// </summary>
		/// <param name="source">The non-generic version <see cref="IEnumerable"/>.</param>
		/// <returns><c>true</c> means not empty, <c>false</c> otherwise.</returns>
		[DebuggerStepThrough]
		public static Boolean IsNotEmpty([CanBeNull] this IEnumerable source)
		{
			var asCollection = source as ICollection;
			if (asCollection != null)
			{
				return asCollection.Count > 0;
			}
			return source != null && source.GetEnumerator().MoveNext();
		}

		/// <summary>
		/// Determines whether the <paramref name="source"/> is null or zero-length.
		/// </summary>
		/// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
		/// <param name="source"> The generic version <see cref="IEnumerable{T}"/>. </param>
		/// <returns> <c>true</c> means empty, <c>false</c> otherwise. </returns>
		[DebuggerStepThrough]
		public static Boolean IsEmpty<TSource>([CanBeNull] this IEnumerable<TSource> source)
		{
			var asCollection = source as ICollection;
			if (asCollection != null)
			{
				return asCollection.Count == 0;
			}
			return source == null || !source.Any();
		}

		/// <summary>
		/// Determines whether the <paramref name="source"/> is neither null nor zero-length.
		/// </summary>
		/// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
		/// <param name="source">The generic version <see cref="IEnumerable{T}"/>.</param>
		/// <returns><c>true</c> means not empty, <c>false</c> otherwise.</returns>
		[DebuggerStepThrough]
		public static Boolean IsNotEmpty<TSource>([CanBeNull] this IEnumerable<TSource> source)
		{
			var asCollection = source as ICollection;
			if (asCollection != null)
			{
				return asCollection.Count > 0;
			}
			return source != null && source.Any();
		}

		/// <summary>
		/// Determines whether the <paramref name="source"/> is in <paramref name="sources"/>.
		/// This is the shortcut of <c>sources.Any(s => s == source)</c>.
		/// </summary>
		/// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
		/// <param name="source">The element to determine whether is in <paramref name="sources"/>.</param>
		/// <param name="sources">The sequence for determining whether <paramref name="source"/> is in.</param>
		/// <returns><c>true</c> means <paramref name="source"/> is in <paramref name="sources"/>, <c>false</c> otherwise.</returns>
		[DebuggerStepThrough]
		public static Boolean IsIn<TSource>([CanBeNull] this TSource source, params TSource[] sources)
		{
			return sources.IsNotEmpty() && sources.Any(item => Equals(item, source));
		}

		/// <summary>
		/// Determines whether the <paramref name="source"/> is in <paramref name="sources"/>.
		/// This is the shortcut of <c>sources.Any(s => s == source)</c>.
		/// </summary>
		/// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
		/// <param name="source">The element to determine whether is in <paramref name="sources"/>.</param>
		/// <param name="comparer">The comparer for <typeparamref name="TSource"/>.</param>
		/// <param name="sources">The sequence for determining whether <paramref name="source"/> is in.</param>
		/// <returns><c>true</c> means <paramref name="source"/> is in <paramref name="sources"/>, <c>false</c> otherwise.</returns>
		/// <exception cref="ArgumentNullException"><paramref name="comparer"/> is null.</exception>
		public static Boolean IsIn<TSource>([CanBeNull] this TSource source, IEqualityComparer<TSource> comparer, params TSource[] sources)
		{
			Ensure.ArgumentNotNull(comparer, "comparer");

			return sources.IsNotEmpty() && sources.Any(item => comparer.Equals(item, source));
		}

		/// <summary>
		/// Determines whether the <paramref name="source"/> is not in <paramref name="sources"/>.
		/// This is the shortcut of <c>sources.All(s => s != source)</c>.
		/// </summary>
		/// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
		/// <param name="source">The element to determine whether is not in <paramref name="sources"/>.</param>
		/// <param name="sources">The sequence for determining whether <paramref name="source"/> is not in.</param>
		/// <returns><c>true</c> means <paramref name="source"/> is not in <paramref name="sources"/>, <c>false</c> otherwise.</returns>
		[DebuggerStepThrough]
		public static Boolean IsNotIn<TSource>([CanBeNull] this TSource source, params TSource[] sources)
		{
			return sources.IsEmpty() || sources.All(item => !Equals(item, source));
		}

		/// <summary>
		/// Determines whether the <paramref name="source"/> is not in <paramref name="sources"/>.
		/// This is the shortcut of <c>sources.All(s => s != source)</c>.
		/// </summary>
		/// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
		/// <param name="source">The element to determine whether is not in <paramref name="sources"/>.</param>
		/// <param name="comparer">The comparer for <typeparamref name="TSource"/>.</param>
		/// <param name="sources">The sequence for determining whether <paramref name="source"/> is not in.</param>
		/// <returns><c>true</c> means <paramref name="source"/> is not in <paramref name="sources"/>, <c>false</c> otherwise.</returns>
		/// <exception cref="ArgumentNullException"><paramref name="comparer"/> is null.</exception>
		[DebuggerStepThrough]
		public static Boolean IsNotIn<TSource>([CanBeNull] this TSource source, IEqualityComparer<TSource> comparer, params TSource[] sources)
		{
			Ensure.ArgumentNotNull(comparer, "comparer");

			return sources.IsEmpty() || sources.All(item => !comparer.Equals(item, source));
		}

		#endregion

		#region Modification

		/// <summary>
		/// Convenient method for <see cref="Enumerable.Concat{TSource}"/> allows compile-time params argument as the collection.
		/// </summary>
		/// <typeparam name="TSource">The elements type.</typeparam>
		/// <param name="first">The collection to be concat as the first part.</param>
		/// <param name="second">The collection (params arguments) to be concat to the tail of <paramref name="first"/>.</param>
		/// <returns>The concated collection.</returns>
		[NotNull]
		public static IEnumerable<TSource> Concat<TSource>([CanBeNull] this IEnumerable<TSource> first, params TSource[] second)
		{
			// ReSharper disable once InvokeAsExtensionMethod
			return Enumerable.Concat(first ?? Enumerable.Empty<TSource>(), second ?? Enumerable.Empty<TSource>());
		}

		/// <summary>
		/// Concat the (params arguments) collection to the head of <paramref name="second"/>.
		/// </summary>
		/// <typeparam name="TSource">The elements type.</typeparam>
		/// <param name="second">The collection (params arguments) to be concat to the head of <paramref name="first"/>.</param>
		/// <param name="first">The collection to be concat as the first part.</param>
		/// <returns>The concated collection.</returns>
		[NotNull]
		public static IEnumerable<TSource> ConcatHead<TSource>([CanBeNull] this IEnumerable<TSource> second, params TSource[] first)
		{
			// ReSharper disable once InvokeAsExtensionMethod
			return Enumerable.Concat(first ?? Enumerable.Empty<TSource>(), second ?? Enumerable.Empty<TSource>());
		}

		/// <summary>
		/// Returns distinct elements from a sequence by using a specified <paramref name="keySelector"/> to select the key for comparing values.
		/// </summary>
		/// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
		/// <typeparam name="TKey">The type of selected key of the elements of the input sequences.</typeparam>
		/// <param name="source">The sequence to remove duplicate elements from.</param>
		/// <param name="keySelector">Selector for select the key from <paramref name="source"/>.</param>
		/// <returns>An <see cref="IEnumerable{TSource}"/> that contains distinct elements from the <paramref name="source"/> sequence.</returns>
		/// <exception cref="ArgumentNullException"><paramref name="keySelector"/> is null.</exception>
		public static IEnumerable<TSource> Distinct<TSource, TKey>([CanBeNull] this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
		{
			Ensure.ArgumentNotNull(keySelector, "keySelector");

			return source.ValueOrDefault(x => x.Distinct(ToEqualityComparer(keySelector)));
		}

		/// <summary>
		/// Returns distinct elements from a sequence by using a specified <paramref name="keySelector"/> to select the key for comparing values.
		/// </summary>
		/// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
		/// <typeparam name="TKey">The type of selected key of the elements of the input sequences.</typeparam>
		/// <param name="source">The sequence to remove duplicate elements from.</param>
		/// <param name="keySelector">Selector for select the key from <paramref name="source"/>.</param>
		/// <param name="keyComparer">The <see cref="IEqualityComparer{T}"/> for the <typeparamref name="TKey"/>.</param>
		/// <returns>An <see cref="IEnumerable{TSource}"/> that contains distinct elements from the <paramref name="source"/> sequence.</returns>
		/// <exception cref="ArgumentNullException"><paramref name="keySelector"/> or <paramref name="keyComparer"/> is null.</exception>
		public static IEnumerable<TSource> Distinct<TSource, TKey>([CanBeNull] this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> keyComparer)
		{
			Ensure.ArgumentNotNull(keySelector, "keySelector");
			Ensure.ArgumentNotNull(keyComparer, "keyComparer");

			return source.ValueOrDefault(x => x.Distinct(ToEqualityComparer(keySelector, keyComparer)));
		}

		#endregion

		#region Iteration

		/// <summary>
		/// Enumerate the <paramref name="source"/> with <paramref name="action"/>.
		/// </summary>
		/// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
		/// <param name="source">The sequence to enumerate. It's null-safe.</param>
		/// <param name="action">The action to do for each elements.</param>
		/// <exception cref="ArgumentNullException"><paramref name="action"/> is null.</exception>
		public static void ForEach<TSource>([CanBeNull] this IEnumerable<TSource> source, [InstantHandle] Action<TSource> action)
		{
			Ensure.ArgumentNotNull(action, "action");

			if (source == null)
			{
				return;
			}

			foreach (var item in source)
			{
				action(item);
			}
		}

		/// <summary>
		/// Enumerate the <paramref name="source"/> with <paramref name="action"/>.
		/// </summary>
		/// <typeparam name="TSource">The type of the elements of <paramref name="source"/>.</typeparam>
		/// <param name="source">The sequence to enumerate. It's null-safe.</param>
		/// <param name="action">The action to do for each elements.</param>
		/// <exception cref="ArgumentNullException"><paramref name="action"/> is null.</exception>
		public static void ForEach<TSource>([CanBeNull] this IEnumerable<TSource> source, [InstantHandle] Action<Int32, TSource> action)
		{
			Ensure.ArgumentNotNull(action, "action");

			if (source == null)
			{
				return;
			}

			var i = 0;
			foreach (var item in source)
			{
				action(i, item);
				i += 1;
			}
		}

		#endregion

		/// <summary>
		/// Generic type helper for <see cref="KeyEqualityComparer{T,TKey}"/>.
		/// </summary>
		private static IEqualityComparer<TSource> ToEqualityComparer<TSource, TKey>(Func<TSource, TKey> keySelector)
		{
			return new KeyEqualityComparer<TSource, TKey>(keySelector);
		}

		/// <summary>
		/// Generic type helper for <see cref="KeyEqualityComparer{T,TKey}"/>.
		/// </summary>
		private static IEqualityComparer<TSource> ToEqualityComparer<TSource, TKey>(Func<TSource, TKey> keySelector, IEqualityComparer<TKey> keyComparer)
		{
			return new KeyEqualityComparer<TSource, TKey>(keySelector, keyComparer);
		}

		private sealed class KeyEqualityComparer<T, TKey> : IEqualityComparer<T>
		{
			private static readonly EqualityComparer<TKey> DefaultKeyEqualityComparer = EqualityComparer<TKey>.Default;

			private readonly Func<T, TKey> keySelector;

			private readonly IEqualityComparer<TKey> equalityComparer;

			public KeyEqualityComparer(Func<T, TKey> keySelector)
			{
				this.keySelector = keySelector;
				this.equalityComparer = DefaultKeyEqualityComparer;
			}

			public KeyEqualityComparer(Func<T, TKey> keySelector, IEqualityComparer<TKey> equalityComparer)
			{
				this.keySelector = keySelector;
				this.equalityComparer = equalityComparer;
			}

			public Boolean Equals(T x, T y)
			{
				return this.equalityComparer.Equals(this.keySelector(x), this.keySelector(y));
			}

			public Int32 GetHashCode(T obj)
			{
				return this.equalityComparer.GetHashCode(this.keySelector(obj));
			}
		}
	}
}
<file_sep>﻿using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Xml;
using System.Xml.Linq;
using Xunit;

//// ReSharper disable PossibleNullReferenceException

namespace Nextension
{
	public class XmlExtensionsTests
	{
		[SuppressMessage("StyleCopPlus.StyleCopPlusRules", "SP2001:CheckAllowedIndentationCharacters", Justification = "Reviewed. Suppression is OK here.")]
		private const String XmlContent = @"
<response>
  <data code='0'>
    <url>http://img.cn/af8200cdee8214?size=m&amp;d&amp;m</url>
    <message>OK</message>
    <success>True</success>
    <count>1</count>
  </data>
</response>";

		private static readonly XElement RootElement = XElement.Parse(XmlContent);

		[Theory]
		[MemberData("ValueOfChild_Data")]
		public void ChildValueForXElement(String source, Type type, String name, Object expected)
		{
			var methodDefinition = new Func<XElement, XName, Object>(XmlExtensions.Value<Object>)
				.Method
				.GetGenericMethodDefinition()
				.MakeGenericMethod(type);

			Object actually;

			try
			{
				actually = methodDefinition.Invoke(null, new Object[] { source.ValueOrDefault(XElement.Parse), (XName)name });
			} catch (Exception e)
			{
				Assert.Equal(expected, e.GetBaseException().GetType());
				return;
			}

			Assert.Equal(expected, actually);
		}


		[Theory]
		[MemberData("ValueOfChild_Data")]
		public void ChildValueForXmlElement(String source, Type type, String name, Object expected)
		{
			var methodDefinition = new Func<XmlElement, XName, Object>(XmlExtensions.Value<Object>)
				.Method
				.GetGenericMethodDefinition()
				.MakeGenericMethod(type);

			XmlElement element = null;
			if (source != null)
			{
				var document = new XmlDocument();
				document.LoadXml(source);
				element = document.DocumentElement;
			}

			Object actually;

			try
			{
				actually = methodDefinition.Invoke(null, new Object[] { element, (XName)name });
			} catch (Exception e)
			{
				Assert.Equal(expected, e.GetBaseException().GetType());
				return;
			}

			Assert.Equal(expected, actually);
		}

		public static IEnumerable<Object[]> ValueOfChild_Data()
		{
			// ReSharper disable once PossibleNullReferenceException
			var source = RootElement.Element("data").ToString(SaveOptions.DisableFormatting);

			yield return new Object[] { source, typeof(String), "url", "http://img.cn/af8200cdee8214?size=m&d&m" };
			yield return new Object[] { source, typeof(String), "code", "0" };
			yield return new Object[] { source, typeof(Int32), "code", 0 };
			yield return new Object[] { source, typeof(Boolean), "code", false };
			yield return new Object[] { source, typeof(Boolean), "success", true };
			yield return new Object[] { source, typeof(String), "unexist", null };
			yield return new Object[] { source, typeof(Int32), "unexist", typeof(InvalidOperationException) };
			yield return new Object[] { null, typeof(String), "whatever", null };
			yield return new Object[] { null, typeof(Int32), "whatever", typeof(InvalidOperationException) };
		}

		[Fact]
		public void InnerXml()
		{
			var dataElement = RootElement.Element("data");

			var dataInnerXml = dataElement.InnerXml();
			Assert.StartsWith("<url>", dataInnerXml);
			Assert.DoesNotContain("\r", dataInnerXml);
			Assert.DoesNotContain("\n", dataInnerXml);
			Assert.Contains("&amp;", dataInnerXml);

			var urlElement = dataElement.Element("url");
			Assert.Equal("http://img.cn/af8200cdee8214?size=m&amp;d&amp;m", urlElement.InnerXml());
			Assert.Equal("http://img.cn/af8200cdee8214?size=m&d&m", urlElement.Value);
		}

		[Fact]
		public void OuterXml()
		{
			var dataElement = RootElement.Element("data");

			var dataOuterXml = dataElement.OuterXml();
			Assert.StartsWith("<data", dataOuterXml);
			Assert.DoesNotContain("\r", dataOuterXml);
			Assert.DoesNotContain("\n", dataOuterXml);
			Assert.Contains("&amp;", dataOuterXml);

			var urlElement = dataElement.Element("url");
			Assert.Equal("<url>http://img.cn/af8200cdee8214?size=m&amp;d&amp;m</url>", urlElement.OuterXml());
		}
	}
}
<file_sep>﻿using System;
using System.Collections;
using System.Collections.Generic;
using Nextension.Annotations;

namespace Nextension
{
	[Serializable]
	class SafeDictionary<TKey, TValue> : IDictionary<TKey, TValue>
	{
		private readonly IDictionary<TKey, TValue> inner;

		/// <summary>
		/// Create a new <see cref="SafeDictionary{TKey,TValue}"/>.
		/// </summary>
		public SafeDictionary()
		{
			this.inner = new Dictionary<TKey, TValue>();
		}

		/// <summary>
		/// Create a <see cref="SafeDictionary{TKey,TValue}"/> that uses <paramref name="dictionary"/> as the inner data.
		/// </summary>
		/// <param name="dictionary">The referenced source dictionary.</param>
		public SafeDictionary([NotNull] IDictionary<TKey, TValue> dictionary)
		{
			this.inner = dictionary;
		}

		public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
		{
			return this.inner.GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return ((IEnumerable)this.inner).GetEnumerator();
		}

		public void Add(KeyValuePair<TKey, TValue> item)
		{
			this.inner.Add(item);
		}

		public void Clear()
		{
			this.inner.Clear();
		}

		public bool Contains(KeyValuePair<TKey, TValue> item)
		{
			return this.inner.Contains(item);
		}

		public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
		{
			this.inner.CopyTo(array, arrayIndex);
		}

		public bool Remove(KeyValuePair<TKey, TValue> item)
		{
			return this.inner.Remove(item);
		}

		public int Count
		{
			get { return this.inner.Count; }
		}

		public bool IsReadOnly
		{
			get { return this.inner.IsReadOnly; }
		}

		public bool ContainsKey(TKey key)
		{
			return this.inner.ContainsKey(key);
		}

		public void Add(TKey key, TValue value)
		{
			this.inner.Add(key, value);
		}

		public bool Remove(TKey key)
		{
			return this.inner.Remove(key);
		}

		public bool TryGetValue(TKey key, out TValue value)
		{
			return this.inner.TryGetValue(key, out value);
		}

		public TValue this[TKey key]
		{
			get
			{
				TValue value;
				return this.TryGetValue(key, out value) ? value : default(TValue);
			}
			set { this.inner[key] = value; }
		}

		public ICollection<TKey> Keys
		{
			get { return this.inner.Keys; }
		}

		public ICollection<TValue> Values
		{
			get { return this.inner.Values; }
		}
	}
}
<file_sep>﻿using System;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using Nextension.Annotations;

namespace Nextension
{
	/// <summary>
	/// The extensions for <see cref="System.Xml"/> and <see cref="System.Xml.Linq"/>.
	/// Should NOT use this class directly.
	/// </summary>
	public static class XmlExtensions
	{
		private static readonly String[] TrueStrings = { "True", "Yes", "Y", "T", "1" };

		private static T ConvertTo<T>(String value)
		{
			if (typeof(T) == typeof(String))
			{
				return (T)(Object)value;
			}

			if (typeof(T) == typeof(Boolean))
			{
				return (T)(Object)ParseBoolean(value);
			}

			return (T)Convert.ChangeType(value, typeof(T));
		}

		private static T NullOrError<T>()
		{
			if (typeof(T).IsClass)
			{
				return default(T); // Return null.
			}

			throw new InvalidOperationException();
		}

		private static Boolean ParseBoolean(String value)
		{
			return TrueStrings.Contains(value, StringComparer.OrdinalIgnoreCase);
		}

		/// <summary>
		/// Get the value of this element and convert it to <typeparamref name="T"/>.
		/// </summary>
		/// <typeparam name="T">The type will be convert to.</typeparam>
		/// <returns>The converted value.</returns>
		public static T Value<T>([CanBeNull] this XElement element)
		{
			return element == null ? NullOrError<T>() : ConvertTo<T>(element.Value);
		}

		/// <summary>
		/// Get child value of <paramref name="element"/> and convert it to <typeparamref name="T"/>.
		/// This method will search the children in the child elements and it's owned attributes.
		/// The search order is element than attribute.
		/// </summary>
		/// <typeparam name="T">The type will be convert to.</typeparam>
		/// <returns>The converted value.</returns>
		public static T Value<T>([CanBeNull] this XElement element, XName name)
		{
			if (element == null)
			{
				return NullOrError<T>();
			}

			String value;
			var childElemnt = element.Element(name);
			if (childElemnt == null)
			{
				var attribute = element.Attribute(name);
				if (attribute == null)
				{
					return NullOrError<T>();
				}

				value = attribute.Value;
			} else
			{
				value = childElemnt.Value;
			}

			return ConvertTo<T>(value);
		}

		/// <summary>
		/// Get the child element's literal value.
		/// </summary>
		/// <returns>The literal value.</returns>
		public static String Value([CanBeNull] this XElement element, XName name)
		{
			return Value<String>(element, name);
		}

		/// <summary>
		/// Get the value of this element and convert it to <typeparamref name="T"/>.
		/// </summary>
		/// <typeparam name="T">The type will be convert to.</typeparam>
		/// <returns>The converted value.</returns>
		public static T Value<T>([CanBeNull] this XmlElement element)
		{
			return element == null ? NullOrError<T>() : ConvertTo<T>(element.Value);
		}

		/// <summary>
		/// Get child value of <paramref name="element"/> and convert it to <typeparamref name="T"/>.
		/// This method will search the children in the child elements and it's owned attributes.
		/// The search order is element than attribute.
		/// </summary>
		/// <typeparam name="T">The type will be convert to.</typeparam>
		/// <returns>The converted value.</returns>
		public static T Value<T>([CanBeNull] this XmlElement element, XName name)
		{
			Ensure.ArgumentNotNull(name, "name");

			if (element == null)
			{
				return NullOrError<T>();
			}

			String value;
			var childElemnts = element.GetElementsByTagName(name.LocalName, name.NamespaceName);
			if (childElemnts.Count == 0)
			{
				var attribute = element.GetAttributeNode(name.LocalName, name.NamespaceName);
				if (attribute == null)
				{
					return NullOrError<T>();
				}

				value = attribute.Value;
			} else
			{
				value = childElemnts[0].InnerText;
			}

			return ConvertTo<T>(value);
		}

		/// <summary>
		/// A convention method for <see cref="Value{T}(XmlElement, XName)"/> that using <see cref="XmlQualifiedName"/> as the <paramref name="name"/>.
		/// </summary>
		/// <seealso cref="Value{T}(XmlElement, XName)"/>
		public static T Value<T>([CanBeNull] this XmlElement element, XmlQualifiedName name)
		{
			Ensure.ArgumentNotNull(name, "name");

			return Value<T>(element, XName.Get(name.Name, name.Namespace));
		}

		/// <summary>
		/// Get the child element's literal value.
		/// </summary>
		/// <returns>The literal value.</returns>
		public static String Value([CanBeNull] this XmlElement element, XName name)
		{
			return Value<String>(element, name);
		}

		/// <summary>
		/// Returns inner-xml (well-formed, no indent, escaped) literal value, null returned if <paramref name="element"/> is null.
		/// (The behavior is similiar to <see cref="XmlElement.InnerXml"/>)
		/// </summary>
		/// <param name="element">The element.</param>
		/// <returns>The inner-xml literal value, null if <paramref name="element"/> is null, otherwise <see cref="String.Empty"/> will be return.</returns>
		public static String InnerXml([CanBeNull] this XElement element)
		{
			if (element == null)
			{
				return null;
			}

			using (var reader = element.CreateReader())
			{
				// Check reader at first element or before-first position.
				if (reader.ReadState == ReadState.Interactive || (reader.ReadState == ReadState.Initial && reader.Read()))
				{
					return reader.ReadInnerXml();
				} else
				{
					return String.Empty;
				}
			}
		}

		/// <summary>
		/// Returns outer-xml (well-formed, no indent, escaped) literal value, null returned if <paramref name="element"/> is null.
		/// (The behavior is similiar to <see cref="XmlElement.OuterXml"/>)
		/// </summary>
		/// <param name="element">The element.</param>
		/// <returns>The outer-xml literal value, null if <paramref name="element"/> is null, otherwise <see cref="String.Empty"/> will be return.</returns>
		public static String OuterXml([CanBeNull] this XElement element)
		{
			if (element == null)
			{
				return null;
			}

			using (var reader = element.CreateReader())
			{
				// Check reader at first element or before-first position.
				if (reader.ReadState == ReadState.Interactive || (reader.ReadState == ReadState.Initial && reader.Read()))
				{
					return reader.ReadOuterXml();
				} else
				{
					return String.Empty;
				}
			}
		}

		/// <summary>
		/// Returns the (unescaped) value if <paramref name="element"/> is a value-element, otherwise the inner-xml (see <see cref="InnerXml"/>) will be returned.
		/// </summary>
		/// <param name="element">The element.</param>
		/// <returns>The inner-value or inner-xml.</returns>
		public static String ValueOrInnerXml([CanBeNull] this XElement element)
		{
			if (element == null)
			{
				return null;
			}

			return element.HasElements ? element.InnerXml() : element.Value;
		}

		/// <summary>
		/// Returns the (unescaped) value if <paramref name="element"/> is a value-element, otherwise the outer-xml (see <see cref="OuterXml"/>) will be returned.
		/// </summary>
		/// <param name="element">The element.</param>
		/// <returns>The inner-value or outer-xml.</returns>
		public static String ValueOrOuterXml([CanBeNull] this XElement element)
		{
			if (element == null)
			{
				return null;
			}

			return element.HasElements ? element.OuterXml() : element.Value;
		}
	}
}
<file_sep>NCommons
========

The useful utilities for .Net platform.
<file_sep>﻿using System;
using System.Threading;
using System.Threading.Tasks;
using Nextension.Annotations;

namespace Nextension
{
	/// <summary>
	/// The extensions for <see cref="Task"/>.
	/// </summary>
	public static class Tasks
	{
		private static readonly Task CompletedTask = Task.FromResult(default(VoidResult));

		private static readonly Task CanceledTask;

		static Tasks()
		{
			var tcs = new TaskCompletionSource<VoidResult>();
			tcs.SetCanceled();
			CanceledTask = tcs.Task;
		}

		/// <summary>
		/// Gets a no-result completed by success <see cref="Task"/>.
		/// To get the <see cref="Task"/> with result, uses <see cref="Task.FromException{TResult}"/>
		/// </summary>
		public static Task Success
		{
			get { return CompletedTask; }
		}

		/// <summary>
		/// Gets a no-result completed by canceled <see cref="Task"/>.
		/// </summary>
		public static Task Canceled()
		{
			return CanceledTask;
		}

		/// <summary>
		/// Gets a completed by canceled <see cref="Task{T}"/>.
		/// </summary>
		/// <typeparam name="T">The result type.</typeparam>
		/// <returns>The canceled task.</returns>
		public static Task<T> Canceled<T>()
		{
			var tcs = new TaskCompletionSource<T>();
			tcs.SetCanceled();
			return tcs.Task;
		}

		/// <summary>
		/// Gets a no-result completed by faulted <see cref="Task"/>
		/// </summary>
		/// <param name="exception">The exception leads to fault.</param>
		/// <returns>The faulted task.</returns>
		public static Task Faulted([NotNull] Exception exception)
		{
			return Faulted<VoidResult>(exception);
		}

		/// <summary>
		/// Gets a completed by faulted <see cref="Task{T}"/>
		/// </summary>
		/// <typeparam name="T">The result type.</typeparam>
		/// <param name="exception">The exception leads to fault.</param>
		/// <returns>The faulted task.</returns>
		public static Task<T> Faulted<T>([NotNull] Exception exception)
		{
			Ensure.ArgumentNotNull(exception, "exception");

			var tcs = new TaskCompletionSource<T>();
			tcs.SetException(exception);
			return tcs.Task;
		}

		/// <summary>
		/// Gets a new non-disposed <see cref="CancellationToken"/> from the origin <paramref name="token"/>.
		/// </summary>
		/// <param name="token">The token.</param>
		/// <returns>A new token.</returns>
		public static CancellationToken GetSafeToken(this CancellationToken token)
		{
			return GetSafeTokenSource(token).Token;
		}

		/// <summary>
		/// Gets a new non-disposed <see cref="CancellationTokenSource"/> from the origin <paramref name="token"/>.
		/// </summary>
		/// <param name="token">The token.</param>
		/// <returns>A new token source.</returns>
		public static CancellationTokenSource GetSafeTokenSource(this CancellationToken token)
		{
			return CancellationTokenSource.CreateLinkedTokenSource(token, CancellationToken.None);
		}

		[Serializable]
		private struct VoidResult
		{
		}
	}
}
<file_sep>﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Xunit;

namespace Nextension
{
	public class EnumerableExtensionsTests
	{
		//// ReSharper disable PossibleMultipleEnumeration
		//// ReSharper disable ExpressionIsAlwaysNull
		[Theory]
		[InlineData(null, true)]
		public void IsEmpty(IEnumerable source, Boolean expect)
		{
			Assert.Equal(expect, source.IsEmpty());
			Assert.Equal(expect, ((IEnumerable<Object>)source).IsEmpty());
			Assert.NotEqual(expect, source.IsNotEmpty());
			Assert.NotEqual(expect, ((IEnumerable<Object>)source).IsNotEmpty());
		}

		[Fact]
		public void IsEmpty()
		{
			this.IsEmpty(Enumerable.Empty<Object>(), true);
			this.IsEmpty(new Object[] { null, null }, false);
			this.IsEmpty(new Object[] { 1, "String" }, false);
		}

		[Fact]
		public void IsIn()
		{
			const String foo = "foo";
			const String @null = null;

			Assert.True(foo.IsIn("foo", "abc"));
			Assert.True(foo.IsNotIn("Foo", "abc"));

			Assert.True(foo.IsIn(StringComparer.OrdinalIgnoreCase, "Foo", "abc"));
			Assert.False(foo.IsNotIn(StringComparer.OrdinalIgnoreCase, "Foo", "abc"));

			Assert.True(@null.IsIn(new String[] { null }));
			Assert.True(foo.IsNotIn((String[])null));
			Assert.True(foo.IsNotIn(/*Empty*/));
		}

		[Fact]
		public void ForEach()
		{
			var source = new[] { 1, 2, 3, 4, 5 };

			Int32[] i = { 0 };
			source.ForEach(item => i[0] += 1);
			Assert.Equal(5, i[0]);

			i[0] = 0;
			source.ForEach((index, item) => i[0] += 1);
			Assert.Equal(5, i[0]);
		}

		[Fact]
		public void ForEach_WithNullSource()
		{
			IEnumerable<Object> source = null;

			source.ForEach(item => { throw new InvalidOperationException("Should not reach here"); });

			source.ForEach((index, item) => { throw new InvalidOperationException("Should not reach here"); });
		}

		[Fact]
		public void Distinct()
		{
			Int32[] source = { 1, 2, 3, 4, 5, 6 };

			var distincted = source.Distinct(i => i % 2);

			Assert.Equal(2, distincted.Count());

			source = null;
			Assert.Null(source.Distinct(i => i));
		}

		[Fact]
		public void Distinct_WithComparer()
		{
			String[] source = { "Foo", "far", "func", "hello" };

			var distincted = source.Distinct(x => x.Substring(0, 1), StringComparer.OrdinalIgnoreCase);

			Assert.Equal(2, distincted.Count());

			Assert.Throws<ArgumentNullException>(() => source.Distinct(x => x.Substring(0, 1), null));

			String[] source2 = null;
			Assert.Null(source2.Distinct(i => i, StringComparer.OrdinalIgnoreCase));
		}

		[Theory]
		[MemberData("ConcatData")]
		public void Concat(IEnumerable<String> first, String[] second, IEnumerable<String> expect)
		{
			var concat = first.Concat(second);

			Assert.Equal(expect, concat);
		}

		public static IEnumerable<Object[]> ConcatData()
		{
			String[] source = { "a", "b", "c" };

			yield return new Object[] { source, new[] { "d" }, new[] { "a", "b", "c", "d" } };
			yield return new Object[] { null, new[] { "d" }, new[] { "d" } };
			yield return new Object[] { source, null, source };
			yield return new Object[] { null, null, Enumerable.Empty<String>() };
		}

		[Theory]
		[MemberData("ConcatHeadData")]
		public void ConcatHead(IEnumerable<String> second, String[] first, IEnumerable<String> expect)
		{
			var concat = second.ConcatHead(first);

			Assert.Equal(expect, concat);
		}

		public static IEnumerable<Object[]> ConcatHeadData()
		{
			String[] source = { "b", "c", "d" };

			yield return new Object[] { source, new[] { "a" }, new[] { "a", "b", "c", "d" } };
			yield return new Object[] { null, new[] { "a" }, new[] { "a" } };
			yield return new Object[] { source, null, source };
			yield return new Object[] { null, null, Enumerable.Empty<String>() };
		}
	}
}
<file_sep>﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Nextension.Annotations;

namespace Nextension
{
	/// <summary>
	/// The extensions for <see cref="IDictionary{TKey,TValue}"/>.
	/// Should NOT use this class directly.
	/// </summary>
	public static class DictionaryExtensions
	{
		#region SafeDictioanry

		/// <summary>
		/// Wrap the <paramref name="source"/> by the access-safe dictionary.
		/// </summary>
		[NotNull]
		public static IDictionary<TKey, TValue> AsSafeDictionary<TKey, TValue>([CanBeNull] this IDictionary<TKey, TValue> source)
		{
			return (source as SafeDictionary<TKey, TValue>) ?? (source == null ? new SafeDictionary<TKey, TValue>() : new SafeDictionary<TKey, TValue>(source));
		}

		/// <summary>
		/// Create a new <see cref="IDictionary{TKey,TValue}"/> and copy all entries in <paramref name="source"/>.
		/// </summary>
		[NotNull]
		public static IDictionary<TKey, TValue> ToSafeDictionary<TKey, TValue>([CanBeNull] this IDictionary<TKey, TValue> source)
		{
			return source == null ? new SafeDictionary<TKey, TValue>() : AsSafeDictionary(new Dictionary<TKey, TValue>(source));
		}

		/// <summary>
		/// Create a new <see cref="IDictionary{TKey,TValue}"/> and copy all entries in <paramref name="source"/> with <paramref name="comparer"/>.
		/// </summary>
		[NotNull]
		public static IDictionary<TKey, TValue> ToSafeDictionary<TKey, TValue>([CanBeNull] this IDictionary<TKey, TValue> source, IEqualityComparer<TKey> comparer)
		{
			Ensure.ArgumentNotNull(comparer, "comparer");

			return source == null ? new SafeDictionary<TKey, TValue>() : AsSafeDictionary(new Dictionary<TKey, TValue>(source, comparer));
		}

		/// <summary>
		/// Create a new <see cref="IDictionary{TKey,TValue}"/>, by using <paramref name="keySelector"/> to select keys and entries of <paramref name="source"/> as values.
		/// A shorcut for <code>source.ToDictionary(keySelector).AsSafeDictionary()</code>.
		/// </summary>
		[NotNull]
		public static IDictionary<TKey, TSource> ToSafeDictionary<TSource, TKey>([CanBeNull] this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
		{
			Ensure.ArgumentNotNull(keySelector, "keySelector");

			return source == null ? new SafeDictionary<TKey, TSource>() : source.ToDictionary(keySelector).AsSafeDictionary();
		}

		/// <summary>
		/// Create a new <see cref="IDictionary{TKey,TValue}"/>, by using <paramref name="keySelector"/> to select keys, with <paramref name="comparer"/>.
		/// A shorcut for <code>source.ToDictionary(keySelector, comparer).AsSafeDictionary()</code>.
		/// </summary>
		/// <exception cref="ArgumentNullException"><paramref name="keySelector"/> returns null, or <paramref name="comparer"/> is null.</exception>
		[NotNull]
		public static IDictionary<TKey, TSource> ToSafeDictionary<TSource, TKey>([CanBeNull] this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
		{
			Ensure.ArgumentNotNull(keySelector, "keySelector");
			Ensure.ArgumentNotNull(comparer, "comparer");

			return source == null ? new SafeDictionary<TKey, TSource>() : source.ToDictionary(keySelector, comparer).AsSafeDictionary();
		}

		/// <summary>
		/// Create a new <see cref="IDictionary{TKey,TValue}"/>, by using <paramref name="keySelector"/> to select keys and <paramref name="elementSeletor"/> to select values.
		/// A shorcut for <code>source.ToDictionary(keySelector, elementSelector).AsSafeDictionary()</code>.
		/// </summary>
		/// <exception cref="ArgumentNullException"><paramref name="keySelector"/> returns null.</exception>
		[NotNull]
		public static IDictionary<TKey, TElement> ToSafeDictionary<TSource, TKey, TElement>([CanBeNull] this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSeletor)
		{
			Ensure.ArgumentNotNull(keySelector, "keySelector");
			Ensure.ArgumentNotNull(elementSeletor, "elementSeletor");

			return source == null ? new SafeDictionary<TKey, TElement>() : source.ToDictionary(keySelector, elementSeletor).AsSafeDictionary();
		}

		/// <summary>
		/// Create a new <see cref="IDictionary{TKey,TValue}"/>, by using <paramref name="keySelector"/> to select keys and <paramref name="elementSeletor"/> to select values, with <paramref name="comparer"/>.
		/// A shorcut for <code>source.ToDictionary(keySelector, elementSelector, comparer).AsSafeDictionary()</code>.
		/// </summary>
		/// <exception cref="ArgumentNullException"><paramref name="keySelector"/> returns null, or <paramref name="comparer"/> is null.</exception>
		[NotNull]
		public static IDictionary<TKey, TElement> ToSafeDictionary<TSource, TKey, TElement>([CanBeNull] this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSeletor, IEqualityComparer<TKey> comparer)
		{
			Ensure.ArgumentNotNull(keySelector, "keySelector");
			Ensure.ArgumentNotNull(elementSeletor, "elementSeletor");
			Ensure.ArgumentNotNull(comparer, "comparer");

			return source == null ? new SafeDictionary<TKey, TElement>() : source.ToDictionary(keySelector, elementSeletor, comparer).AsSafeDictionary();
		}

		#endregion

		#region TryGetValue

		/// <summary>
		/// Try getting the value in the specific type <typeparamref name="TOutValue"/> from the <paramref name="source"/>.
		/// </summary>
		/// <typeparam name="TKey">The key type of the <paramref name="source"/> dictionary.</typeparam>
		/// <typeparam name="TSourceValue">The value type of the <paramref name="source"/> dictionary.</typeparam>
		/// <typeparam name="TOutValue">The type of value you want cast to.</typeparam>
		/// <param name="source">The source dictionary.</param>
		/// <param name="key">The key to find in the <paramref name="source"/>.</param>
		/// <param name="value">The result value, if returns <c>true</c> this value is valid, else the <c>default(<typeparamref name="TOutValue"/>)</c> will be set.</param>
		/// <param name="convert">Indicates should use the <see cref="Convert.ChangeType(object,System.Type)"/> to convert the value.</param>
		/// <returns><c>true</c> indicates the <paramref name="value"/> is valid, otherwise <c>false</c>.</returns>
		public static Boolean TryGetValue<TKey, TSourceValue, TOutValue>([CanBeNull] this IDictionary<TKey, TSourceValue> source, TKey key, out TOutValue value, Boolean convert = false)
		{
			if (source != null)
			{
				TSourceValue sourceValue;

				if (source.TryGetValue(key, out sourceValue))
				{
					// Try cast to TOutValue.
					if (sourceValue.TryCast(out value))
					{
						return true;
					}

					// Try convert if convertible.
					if (convert && sourceValue.TryConvert(out value))
					{
						return true;
					}
				}
			}

			value = default(TOutValue);
			return false;
		}

		/// <summary>
		/// Try getting the value from the non-generic version <see cref="IDictionary"/> and change the value to the specific type <typeparamref name="TValue"/>.
		/// </summary>
		/// <typeparam name="TValue">The type of value you want change to.</typeparam>
		/// <param name="source">The source dictionary.</param>
		/// <param name="key">The key to find in the <paramref name="source"/>.</param>
		/// <param name="value">The result value, if returns <c>true</c> this value is valid, else the <c>default(<typeparamref name="TValue"/>)</c> will be set.</param>
		/// <param name="convert">Indicates should use the <see cref="Convert.ChangeType(object,System.Type)"/> to convert the value.</param>
		/// <returns><c>true</c> indicates the <paramref name="value"/> is valid, otherwise <c>false</c>.</returns>
		public static Boolean TryGetValue<TValue>([CanBeNull] this IDictionary source, Object key, out TValue value, Boolean convert = false)
		{
			if (source != null)
			{
				var sourceValue = source[key];

				if (sourceValue != null)
				{
					// Try cast to TOutValue.
					if (sourceValue.TryCast(out value))
					{
						return true;
					}

					// Try convert if convertible.
					if (convert && sourceValue.TryConvert(out value))
					{
						return true;
					}
				}
			}

			value = default(TValue);
			return false;
		}

		/// <summary>
		/// Try get value or default.
		/// </summary>
		public static TValue TryGetValue<TSource, TValue>([CanBeNull] this IDictionary<TSource, TValue> source, TSource key)
		{
			TValue value;
			return (source != null && source.TryGetValue(key, out value)) ? value : default(TValue);
		}

		#endregion

	}
}
<file_sep>﻿using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

// 有关程序集的常规信息通过以下
// 特性集控制。更改这些特性值可修改
// 与程序集关联的信息。
#if NETFX45
[assembly: AssemblyTitle("Nextension")]
[assembly: AssemblyDescription("The useful extensions for .NET 4.5")]
[assembly: AssemblyProduct("Nextension")]
#elif WINRT81
[assembly: AssemblyTitle("NCommons.WinRT")]
[assembly: AssemblyDescription("The commons utilities for WinRT 8.1")]
[assembly: AssemblyProduct("NCommons.WinRT")]
#else
#error Not supported or undefined platform.
#endif
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Nextension Project")]
[assembly: AssemblyCopyright("Copyright © MiNG 2015")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]

// 将 ComVisible 设置为 false 使此程序集中的类型
// 对 COM 组件不可见。  如果需要从 COM 访问此程序集中的类型，
// 则将该类型上的 ComVisible 特性设置为 true。
[assembly: ComVisible(false)]

// 如果此项目向 COM 公开，则下列 GUID 用于类型库的 ID
[assembly: Guid("bc4f113e-4199-4606-8bf1-aa8ab92c775c")]

// 程序集的版本信息由下面四个值组成:
//
//      主版本
//      次版本
//      生成号
//      修订号
//
// 可以指定所有这些值，也可以使用“生成号”和“修订号”的默认值，
// 方法是按如下所示使用“*”:
// [assembly: AssemblyVersion("1.0.*")]
#if NETFX45
[assembly: AssemblyVersion("1.0.0")]
[assembly: AssemblyFileVersion("1.0.0")]
#elif WINRT81
[assembly: AssemblyVersion("1.0.0.81")]
[assembly: AssemblyFileVersion("1.0.0.81")]
#else
#error Not supported or undefined platform.
#endif

#if NETFX45
[assembly: InternalsVisibleTo("Nextension.Tests, PublicKey=002400000480000094000000060200000024000052534131000400000100010059447075141c25a123d2b3c6ac7c23a0c8ba53aca7b675643ee425d403a4db96cc819339eb6a58d6fa737792c4ed1cc65a3fb9807819f69d40a0a936db1ef7f301d2f048bb0315cf2be48e52338a4dce39d4de46bec004c7b8eb7dfa5b3205e3e6da6fa7ecf12ce3e4b1935cf7c6e43e2dd4b1668e8b34ec18565f5677c283e3")]
#elif WINRT81
//TODO: [assembly: InternalsVisibleTo("NCommons.Tests")]
#endif
<file_sep>﻿using System;
using System.Diagnostics;
using Nextension.Annotations;

namespace Nextension
{
	/// <summary>
	/// The extensions for enums.
	/// Should NOT use this class directly.
	/// </summary>
	public static class EnumExtensions
	{
		/// <summary>
		/// Detect whether the <paramref name="source"/> is defined in the enum-declaration.
		/// </summary>
		/// <param name="source">The enum object. <c>null</c> will always be assumed undefined.</param>
		/// <returns>If <paramref name="source"/> is a defined value returns <c>true</c>, otherwise <c>false</c>.</returns>
		[DebuggerStepThrough]
		public static Boolean IsDefined([CanBeNull] this Enum source)
		{
			return source != null && Enum.IsDefined(source.GetType(), source);
		}

		/// <summary>
		/// Detect whether the <paramref name="source"/> is a valid representation of the <typeparamref name="TEnum"/>.
		/// The valid enum representation is: enum instance, enum literal, enum underlying type instance, enum underlying type literal.
		/// </summary>
		/// <typeparam name="TEnum">The enum type.</typeparam>
		/// <param name="source">The enum object. <c>null</c> will always be assumed undefined.</param>
		/// <returns>If <paramref name="source"/> is a defined value returns <c>true</c>, otherwise <c>false</c>.</returns>
		[DebuggerStepThrough]
		public static Boolean IsEnumOf<TEnum>([CanBeNull] this Object source)
			where TEnum : struct
		{
			if (!typeof(TEnum).IsEnum)
			{
				throw new ArgumentException(Properties.Resources.TypeMustBeEnum);
			}

			return IsEnumOf(source, typeof(TEnum));
		}

		/// <summary>
		/// Detect whether the <paramref name="source"/> is a valid representation of the <paramref name="enumType"/>.
		/// The valid enum representation is: enum instance, enum literal, enum underlying type instance, enum underlying type literal.
		/// </summary>
		/// <param name="source">The enum object. <c>null</c> will always be assumed undefined.</param>
		/// <param name="enumType">The enum type.</param>
		/// <returns>If <paramref name="source"/> is a defined value returns <c>true</c>, otherwise <c>false</c>.</returns>
		[DebuggerStepThrough]
		public static Boolean IsEnumOf([CanBeNull] this Object source, Type enumType)
		{
			Ensure.ArgumentNotNull(enumType, "enumType");

			if (!enumType.IsEnum)
			{
				throw new ArgumentException(Properties.Resources.TypeMustBeEnum, "enumType");
			}

			if (source == null)
			{
				return false;
			}

			if (!source.GetType().IsEnum || source.GetType() == enumType)
			{
				return Enum.IsDefined(enumType, source);
			}

			return false;
		}

		/// <summary>
		/// Change the enum to their underlying type.
		/// </summary>
		/// <param name="source">The enum object, passing <c>null</c> is permitted.</param>
		/// <returns>The boxed instance of the enum underlying type, <c>null</c> is returned is <paramref name="source"/> is.</returns>
		[DebuggerStepThrough]
		public static Object ToUndelyingType([CanBeNull] this Enum source)
		{
			if (source == null)
			{
				return null;
			}

			var underlyingObject = Convert.ChangeType(source, source.GetTypeCode());

			return underlyingObject;
		}
	}
}
<file_sep>﻿using System;
using System.Collections;
using Xunit;

namespace Nextension
{
	public class EnsureTests
	{
		[Theory]
		[InlineData(null, true)]
		[InlineData(default(Int32), false)]
		[InlineData("", false)]
		public void EnsureArgumentNotNull(Object argument, Boolean shouldCorrupt)
		{
			try
			{
				Ensure.ArgumentNotNull(argument, "argument");
				Assert.False(shouldCorrupt);
			} catch (ArgumentNullException)
			{
				Assert.True(shouldCorrupt);
			}

			try
			{
				Ensure.ArgumentNotNull(argument, "argument", "Argument should not be null.");
				Assert.False(shouldCorrupt);
			} catch (ArgumentNullException)
			{
				Assert.True(shouldCorrupt);
			}
		}

		[Fact]
		public void EnsureArgumentNotNull()
		{
			this.EnsureArgumentNotNull(Helpers.NonGenericEmptyEnumerable, false);
			this.EnsureArgumentNotNull(Helpers.GenericEmptyEnumerable<Object>(), false);
		}

		[Theory]
		[InlineData(null, true)]
		[InlineData("", true)]
		public void EnsureArgumentNotEmpty(IEnumerable argument, Boolean shouldCorrupt)
		{
			try
			{
				// ReSharper disable once PossibleMultipleEnumeration
				Ensure.ArgumentNotEmpty(argument, "argument");
				Assert.False(shouldCorrupt);
			} catch (ArgumentNullException)
			{
				throw new InvalidOperationException("Unexpected exception.");
			} catch (ArgumentException)
			{
				Assert.True(shouldCorrupt);
			}

			try
			{
				// ReSharper disable once PossibleMultipleEnumeration
				Ensure.ArgumentNotEmpty(argument, "argument", "Argument should not be null.");
				Assert.False(shouldCorrupt);
			} catch (ArgumentNullException)
			{
				throw new InvalidOperationException("Unexpected exception.");
			} catch (ArgumentException)
			{
				Assert.True(shouldCorrupt);
			}
		}

		[Fact]
		public void EnsureArgumentNotEmpty()
		{
			this.EnsureArgumentNotEmpty(Helpers.NonGenericEmptyEnumerable, true);
			this.EnsureArgumentNotEmpty(Helpers.GenericEmptyEnumerable<Object>(), true);
			this.EnsureArgumentNotEmpty(new[] { 1, 2, 3 }, false);
		}
	}
}
<file_sep>﻿using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using Nextension.Annotations;

namespace Nextension
{
	/// <summary>
	/// The extension for every object.
	/// Should NOT use this class directly.
	/// </summary>
	public static class ObjectExtensions
	{
		[DebuggerStepThrough]
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static TResult ValueOrDefault<TSource, TResult>([CanBeNull] this TSource source, [NotNull] Func<TSource, TResult> valuer)
			where TSource : class
		{
			return (source == null) ? default(TResult) : valuer(source);
		}

		[DebuggerStepThrough]
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static TResult ValueOrDefault<TSource, TResult>([CanBeNull] this TSource source, [NotNull] Func<TSource, TResult> valuer, TResult defaultValue)
			where TSource : class
		{
			return (source == null) ? defaultValue : valuer(source);
		}

		[DebuggerStepThrough]
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static TResult ValueOrDefault<TSource, TResult>([CanBeNull] this TSource source, [NotNull] Func<TSource, TResult> valuer, [NotNull] Func<TResult> defaultValuer)
			where TSource : class
		{
			return (source == null) ? defaultValuer() : valuer(source);
		}

		/// <summary>
		/// Provides method like "as" convert for using in the lambda expression.
		/// NOTE: Be care using with the value-types, the boxing mechanism may causes the performance issue.
		/// </summary>
		[DebuggerStepThrough]
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static T As<T>([CanBeNull] this Object source)
			where T : class
		{
			return source as T;
		}

		/// <summary>
		/// Provides method like "is" convert for using in the lambda expression.
		/// NOTE: Be care using with the value-types, the boxing mechanism may causes the performance issue.
		/// </summary>
		[DebuggerStepThrough]
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static Boolean InstanceOf<T>([CanBeNull] this Object source)
		{
			return source is T;
		}

		/// <summary>
		/// Try cast the <paramref name="source"/> to the specific type <typeparamref name="T"/> without exceptions.
		/// Beware, the compile-time casting operator cannot be used in the runtime casting.
		/// NOTE: Be care using with the value-types, the boxing mechanism may causes the performance issue.
		/// </summary>
		public static Boolean TryCast<T>([CanBeNull] this Object source, out T value)
		{
			// ReSharper disable once CanBeReplacedWithTryCastAndCheckForNull
			if (source is T)
			{
				value = (T)source;
				return true;
			} else
			{
				value = default(T);
				return false;
			}
		}

		/// <summary>
		/// Try convert the <paramref name="source"/> to the specific type <typeparamref name="T"/> by using <see cref="Convert.ChangeType(Object, Type)"/>.
		/// NOTE: Be care using with the value-types, the boxing mechanism may causes the performance issue.
		/// </summary>
		public static Boolean TryConvert<T>([CanBeNull] this Object source, out T value)
		{
			Exception _;
			return TryConvert(source, out value, out _);
		}

		/// <summary>
		/// Try convert the <paramref name="source"/> to the specific type <typeparamref name="T"/> by using <see cref="Convert.ChangeType(Object, Type)"/>.
		/// NOTE: Be care using with the value-types, the boxing mechanism may causes the performance issue.
		/// </summary>
		public static Boolean TryConvert<T>([CanBeNull] this Object source, out T value, out Exception exception)
		{
			var type = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T);  // Unwrap the type if it is nullable.
			try
			{
				value = (T)Convert.ChangeType(source, type);
				exception = null;
				return true;
			} catch (Exception e)
			{
				value = default(T);
				exception = e;
				return false;
			}
		}
	}
}
<file_sep>﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace Nextension
{
	static class DataSources
	{
		private static readonly IDictionary<Object, Object> Mapping = new Dictionary<Object, Object>();

		static DataSources()
		{
			Mapping.Add(PlaceHolder.EmptyCollection, Enumerable.Empty<Object>());
			Mapping.Add(PlaceHolder.BlankCollection, new Object[] { null, null });
			Mapping.Add(PlaceHolder.NonBlankCollection, new Object[] { 0, String.Empty });
		}

		public static IEnumerable<Object[]> GetData(params Object[] args)
		{
			yield return args.Select(arg => Mapping.ContainsKey(arg) ? Mapping[arg] : arg).ToArray();
		}

		public enum PlaceHolder
		{
			None,

			EmptyCollection,
			BlankCollection,
			NonBlankCollection,
		}
	}
}
<file_sep>﻿using System;
using Xunit;

namespace Nextension
{
	public class StringExtensionsTests
	{
		[Theory]
		[InlineData(null, true)]
		[InlineData("", true)]
		[InlineData(" ", false)]
		[InlineData("\t", false)]
		[InlineData("\r", false)]
		[InlineData("foo", false)]
		public void IsEmpty(String source, Boolean expected)
		{
			Assert.Equal(expected, source.IsEmpty());
			Assert.NotEqual(expected, source.IsNotEmpty());
		}

		[Theory]
		[InlineData(null, true)]
		[InlineData("", true)]
		[InlineData(" ", true)]
		[InlineData("\t", true)]
		[InlineData("\r", true)]
		[InlineData("foo", false)]
		public void IsBlank(String source, Boolean expected)
		{
			Assert.Equal(expected, source.IsBlank());
			Assert.NotEqual(expected, source.IsNotBlank());
		}

		[Theory]
		[InlineData(null, false)]
		[InlineData("", false)]
		[InlineData("0", false)]
		[InlineData("00", true)]
		public void RegexMatch_TwoDigits(String source, Boolean expected)
		{
			Assert.Equal(expected, source.RegexMatch(@"\d{2}"));
		}

		[Fact]
		public void RegexMatch_NullPattern()
		{
			Assert.Throws<ArgumentNullException>(() => "foo".RegexMatch(null));
		}

		[Theory]
		[InlineData(null, null)]
		[InlineData("", "")]
		[InlineData("0", "0")]
		[InlineData("0 0\t0\r0\n", "0000")]
		public void RegexMatch_RemoveWhitespaces(String source, String expected)
		{
			Assert.Equal(expected, source.RegexReplace(@"\s", String.Empty));
		}

		[Fact]
		public void RegexReplace_NullPattern()
		{
			Assert.Throws<ArgumentNullException>(() => "foo".RegexReplace(null, String.Empty));
		}
	}
}
