Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ee30ce0

Browse files
Fix #284
1 parent d54686e commit ee30ce0

17 files changed

+995
-136
lines changed

src/ImageProcessor.Web.UnitTests/ExtendedColorTypeConverterTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ public class ExtendedColorTypeConverterTests
3535
[TestCase("blue")]
3636
public void ExtendedColorTypeConverterParsesColors(string input)
3737
{
38-
ExtendedColorTypeConverter converter = new ExtendedColorTypeConverter();
39-
object convertFrom = converter.ConvertFrom(null, null, input);
38+
ColorTypeConverter converter = new ColorTypeConverter();
39+
object convertFrom = converter.ConvertFrom(null, input, typeof(Color));
4040
if (convertFrom != null)
4141
{
4242
Color color = (Color)convertFrom;
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// --------------------------------------------------------------------------------------------------------------------
2+
// <copyright file="ObjectExtensions.cs" company="James South">
3+
// Copyright (c) James South.
4+
// Licensed under the Apache License, Version 2.0.
5+
// </copyright>
6+
// <summary>
7+
// Extensions methods for <see cref="object" />.
8+
// </summary>
9+
// --------------------------------------------------------------------------------------------------------------------
10+
11+
namespace ImageProcessor.Web.Extensions
12+
{
13+
/// <summary>
14+
/// Extensions methods for <see cref="object"/>.
15+
/// </summary>
16+
internal static class ObjectExtensions
17+
{
18+
/// <summary>
19+
/// Gets a value indicating whether the <see cref="object"/> is null or an empty <see cref="string"/>.
20+
/// </summary>
21+
/// <param name="value">The object to test against.</param>
22+
/// <returns>True; if the value is null or an empty string; otherwise; false.</returns>
23+
public static bool IsNullOrEmptyString(this object value)
24+
{
25+
return value == null || value as string == string.Empty;
26+
}
27+
}
28+
}

src/ImageProcessor.Web/Extensions/StringExtensions.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
namespace ImageProcessor.Web.Extensions
1212
{
1313
using System;
14+
using System.Collections.Generic;
1415
using System.Globalization;
1516
using System.Linq;
1617
using System.Security.Cryptography;
@@ -65,7 +66,7 @@ public static string ToSHA1Fingerprint(this string expression)
6566
}
6667
}
6768
#endregion
68-
69+
6970
#region Numbers
7071
/// <summary>
7172
/// Creates an array of integers scraped from the String.
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
// --------------------------------------------------------------------------------------------------------------------
2+
// <copyright file="TypeInferenceExtensions.cs" company="James South">
3+
// Copyright (c) James South.
4+
// Licensed under the Apache License, Version 2.0.
5+
// </copyright>
6+
// <summary>
7+
// Extensions methods for <see cref="T:System.Type" /> for inferring type properties.
8+
// Most of this code was adapted from the Entity Framework
9+
// </summary>
10+
// --------------------------------------------------------------------------------------------------------------------
11+
12+
namespace ImageProcessor.Web.Extensions
13+
{
14+
using System;
15+
using System.Collections.Generic;
16+
using System.Linq;
17+
18+
/// <summary>
19+
/// Extensions methods for <see cref="T:System.Type"/> for inferring type properties.
20+
/// Most of this code was adapted from the Entity Framework
21+
/// </summary>
22+
internal static class TypeInferenceExtensions
23+
{
24+
/// <summary>
25+
/// Determines whether the specified type is an enumerable of the given argument type.
26+
/// </summary>
27+
/// <param name="type">The type.</param>
28+
/// <param name="typeArgument">The generic type argument.</param>
29+
/// <returns>
30+
/// True if the type is an enumerable of the given argument type otherwise; false.
31+
/// </returns>
32+
public static bool IsEnumerableOfType(this Type type, Type typeArgument)
33+
{
34+
Type t = type.TryGetElementType(typeof(IEnumerable<>));
35+
return t != null && typeArgument.IsAssignableFrom(t);
36+
}
37+
38+
/// <summary>
39+
/// Determines whether the specified type is a collection type.
40+
/// </summary>
41+
/// <param name="type">The type.</param>
42+
/// <returns>True if the type is a collection type otherwise; false.</returns>
43+
public static bool IsCollectionType(this Type type)
44+
{
45+
return type.TryGetElementType(typeof(ICollection<>)) != null;
46+
}
47+
48+
/// <summary>
49+
/// Determines whether the specified type is an enumerable type.
50+
/// </summary>
51+
/// <param name="type">The type.</param>
52+
/// <returns>True if the type is an enumerable type otherwise; false.</returns>
53+
public static bool IsEnumerableType(this Type type)
54+
{
55+
return type.TryGetElementType(typeof(IEnumerable<>)) != null;
56+
}
57+
58+
/// <summary>
59+
/// Determines whether the specified type is an enumerable type containing a
60+
/// key value pair as the generic type parameter.
61+
/// <remarks>
62+
/// <see cref="M:Enumerable.FirstOrDefault"/> will throw an error when passed an
63+
/// <see cref="T:IEnumerable{KeyValuePair{,}}"/> this includes <see cref="T:Dictionary{,}"/>.
64+
/// </remarks>
65+
/// </summary>
66+
/// <param name="type">The type.</param>
67+
/// <returns>
68+
/// True if the type is an enumerable type with the generic parameter of a key/value
69+
/// pair otherwise; false.</returns>
70+
public static bool IsEnumerableOfKeyValueType(this Type type)
71+
{
72+
return type.TryGetElementType(typeof(IDictionary<,>)) != null ||
73+
(type.IsEnumerableType() && type.IsGenericType && type.GenericTypeArguments.Any()
74+
&& type.GenericTypeArguments[0].IsGenericType
75+
&& type.GenericTypeArguments[0].GetGenericTypeDefinition() == typeof(KeyValuePair<,>));
76+
}
77+
78+
/// <summary>
79+
/// Determines whether the specified type is an enumerable type that is safe to cast
80+
/// following processing via a type converter.
81+
/// <remarks>
82+
/// This should exclude <see cref="T:string"/>, <see cref="T:Dictionary{,}"/>
83+
/// </remarks>
84+
/// </summary>
85+
/// <param name="type">The type.</param>
86+
/// <returns>True if the type is a cast-safe, enumerable type otherwise; false.</returns>
87+
public static bool IsCastableEnumerableType(this Type type)
88+
{
89+
// String, though enumerable have no generic arguments.
90+
// Types with more than one generic argument cnnot be cast.
91+
// Dictionary, though enumerable, requires linq to convert and shouldn't be attempted anyway.
92+
return type.IsEnumerableType() && type.GenericTypeArguments.Any()
93+
&& type.GenericTypeArguments.Length == 1
94+
&& type.TryGetElementType(typeof(IDictionary<,>)) == null;
95+
}
96+
97+
/// <summary>
98+
/// Determine if the given type implements the given generic interface or derives from the given generic type,
99+
/// and if so return the element type of the collection. If the type implements the generic interface several times
100+
/// <c>null</c> will be returned.
101+
/// </summary>
102+
/// <param name="type">The type to examine. </param>
103+
/// <param name="interfaceOrBaseType"> The generic type to be queried for. </param>
104+
/// <returns>
105+
/// <c>null</c> if <paramref name="interfaceOrBaseType"/> isn't implemented or implemented multiple times,
106+
/// otherwise the generic argument.
107+
/// </returns>
108+
public static Type TryGetElementType(this Type type, Type interfaceOrBaseType)
109+
{
110+
if (!type.IsGenericTypeDefinition)
111+
{
112+
Type[] types = GetGenericTypeImplementations(type, interfaceOrBaseType).ToArray();
113+
return types.Length == 1 ? types[0].GetGenericArguments().FirstOrDefault() : null;
114+
}
115+
116+
return null;
117+
}
118+
119+
/// <summary>
120+
/// Determine if the given type implements the given generic interface or derives from the given generic type,
121+
/// and if so return the concrete types implemented.
122+
/// </summary>
123+
/// <param name="type"> The type to examine. </param>
124+
/// <param name="interfaceOrBaseType"> The generic type to be queried for. </param>
125+
/// <returns>
126+
/// The generic types constructed from <paramref name="interfaceOrBaseType"/> and implemented by <paramref name="type"/>.
127+
/// </returns>
128+
public static IEnumerable<Type> GetGenericTypeImplementations(this Type type, Type interfaceOrBaseType)
129+
{
130+
if (!type.IsGenericTypeDefinition)
131+
{
132+
return (interfaceOrBaseType.IsInterface ? type.GetInterfaces() : type.GetBaseTypes())
133+
.Union(new[] { type })
134+
.Where(t => t.IsGenericType && t.GetGenericTypeDefinition() == interfaceOrBaseType);
135+
}
136+
137+
return Enumerable.Empty<Type>();
138+
}
139+
140+
/// <summary>
141+
/// Gets the base types that the given type inherits from
142+
/// </summary>
143+
/// <param name="type">The <see cref="Type"/> to get the base types from.</param>
144+
/// <returns>A collection of base types that the given type inherits from.</returns>
145+
public static IEnumerable<Type> GetBaseTypes(this Type type)
146+
{
147+
type = type.BaseType;
148+
149+
while (type != null)
150+
{
151+
yield return type;
152+
153+
type = type.BaseType;
154+
}
155+
}
156+
157+
/// <summary>
158+
/// Gets the type of the enumerable object
159+
/// </summary>
160+
/// <param name="type">The <see cref="Type"/> to check.</param>
161+
/// <returns>The type of the enumerable.</returns>
162+
public static Type GetEnumerableType(this Type type)
163+
{
164+
List<Type> interfaces = type.GetInterfaces().ToList();
165+
if (type.IsInterface && interfaces.All(i => i != type))
166+
{
167+
interfaces.Add(type);
168+
}
169+
170+
return interfaces
171+
.Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEnumerable<>))
172+
.Select(i => i.GetGenericArguments()[0]).FirstOrDefault();
173+
}
174+
}
175+
}

0 commit comments

Comments
 (0)