Skip to content
This repository was archived by the owner on Dec 24, 2022. It is now read-only.

Commit 9cb0a0a

Browse files
committed
Support creating instances from interfaces of common collections and arrays
1 parent bb24c3e commit 9cb0a0a

File tree

3 files changed

+123
-32
lines changed

3 files changed

+123
-32
lines changed

src/ServiceStack.Text/ReflectionExtensions.cs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,22 @@ public static Type GetGenericType(this Type type)
8888
return null;
8989
}
9090

91+
public static Type GetTypeWithGenericTypeDefinitionOfAny(this Type type, params Type[] genericTypeDefinitions)
92+
{
93+
foreach (var genericTypeDefinition in genericTypeDefinitions)
94+
{
95+
var genericType = type.GetTypeWithGenericTypeDefinitionOf(genericTypeDefinition);
96+
if (genericType == null && type == genericTypeDefinition)
97+
{
98+
genericType = type;
99+
}
100+
101+
if (genericType != null)
102+
return genericType;
103+
}
104+
return null;
105+
}
106+
91107
public static bool IsOrHasGenericInterfaceTypeOf(this Type type, Type genericTypeDefinition)
92108
{
93109
return (type.GetTypeWithGenericTypeDefinitionOf(genericTypeDefinition) != null)
@@ -367,6 +383,37 @@ public static EmptyCtorDelegate GetConstructorMethod(string typeName)
367383

368384
public static EmptyCtorDelegate GetConstructorMethodToCache(Type type)
369385
{
386+
if (type.IsInterface)
387+
{
388+
if (type.HasGenericType())
389+
{
390+
var genericType = type.GetTypeWithGenericTypeDefinitionOfAny(
391+
typeof(IDictionary<,>));
392+
393+
if (genericType != null)
394+
{
395+
var keyType = genericType.GenericTypeArguments()[0];
396+
var valueType = genericType.GenericTypeArguments()[1];
397+
return GetConstructorMethodToCache(typeof(Dictionary<,>).MakeGenericType(keyType, valueType));
398+
}
399+
400+
genericType = type.GetTypeWithGenericTypeDefinitionOfAny(
401+
typeof(IEnumerable<>),
402+
typeof(ICollection<>),
403+
typeof(IList<>));
404+
405+
if (genericType != null)
406+
{
407+
var elementType = genericType.GenericTypeArguments()[0];
408+
return GetConstructorMethodToCache(typeof(List<>).MakeGenericType(elementType));
409+
}
410+
}
411+
}
412+
else if (type.IsArray)
413+
{
414+
return () => Array.CreateInstance(type.GetElementType(), 0);
415+
}
416+
370417
var emptyCtor = type.GetEmptyConstructor();
371418
if (emptyCtor != null)
372419
{

tests/ServiceStack.Text.Tests/ReflectionExtensionTests.cs

Lines changed: 42 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -6,41 +6,41 @@
66

77
namespace ServiceStack.Text.Tests
88
{
9+
public class TestModel
10+
{
11+
public TestModel()
12+
{
13+
var i = 0;
14+
this.PublicInt = i++;
15+
this.PublicGetInt = i++;
16+
this.PublicSetInt = i++;
17+
this.PublicIntField = i++;
18+
this.PrivateInt = i++;
19+
this.ProtectedInt = i++;
20+
}
21+
22+
public int PublicInt { get; set; }
23+
24+
public int PublicGetInt { get; private set; }
25+
26+
public int PublicSetInt { private get; set; }
27+
28+
public int PublicIntField;
29+
30+
private int PrivateInt { get; set; }
31+
32+
protected int ProtectedInt { get; set; }
33+
34+
public int IntMethod()
35+
{
36+
return this.PublicInt;
37+
}
38+
}
939

1040
[TestFixture]
1141
public class ReflectionExtensionTests
1242
: TestBase
1343
{
14-
public class TestModel
15-
{
16-
public TestModel()
17-
{
18-
var i = 0;
19-
this.PublicInt = i++;
20-
this.PublicGetInt = i++;
21-
this.PublicSetInt = i++;
22-
this.PublicIntField = i++;
23-
this.PrivateInt = i++;
24-
this.ProtectedInt = i++;
25-
}
26-
27-
public int PublicInt { get; set; }
28-
29-
public int PublicGetInt { get; private set; }
30-
31-
public int PublicSetInt { private get; set; }
32-
33-
public int PublicIntField;
34-
35-
private int PrivateInt { get; set; }
36-
37-
protected int ProtectedInt { get; set; }
38-
39-
public int IntMethod()
40-
{
41-
return this.PublicInt;
42-
}
43-
}
4444

4545
[Test]
4646
public void Only_serializes_public_readable_properties()
@@ -52,5 +52,16 @@ public void Only_serializes_public_readable_properties()
5252

5353
Serialize(model);
5454
}
55-
}
55+
56+
[Test]
57+
public void Can_create_instances_of_common_collections()
58+
{
59+
Assert.That(typeof(IEnumerable<TestModel>).CreateInstance() as IEnumerable<TestModel>, Is.Not.Null);
60+
Assert.That(typeof(ICollection<TestModel>).CreateInstance() as ICollection<TestModel>, Is.Not.Null);
61+
Assert.That(typeof(IList<TestModel>).CreateInstance() as IList<TestModel>, Is.Not.Null);
62+
Assert.That(typeof(IDictionary<string, TestModel>).CreateInstance() as IDictionary<string, TestModel>, Is.Not.Null);
63+
Assert.That(typeof(IDictionary<int, TestModel>).CreateInstance() as IDictionary<int, TestModel>, Is.Not.Null);
64+
Assert.That(typeof(TestModel[]).CreateInstance() as TestModel[], Is.Not.Null);
65+
}
66+
}
5667
}

tests/ServiceStack.Text.Tests/StructTests.cs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
using System.Globalization;
55
using System.Linq;
66
using System.Threading;
7-
using System.Windows;
87
using NUnit.Framework;
98
using ServiceStack.Text.Common;
109

@@ -281,4 +280,38 @@ public struct UserStruct
281280
public int Id { get; set; }
282281
public string Name { get; set; }
283282
}
283+
284+
public struct Rect : IFormattable
285+
{
286+
double x;
287+
double y;
288+
double width;
289+
double height;
290+
291+
public Rect(double x, double y, double width, double height)
292+
{
293+
if (width < 0 || height < 0)
294+
throw new ArgumentException("width and height must be non-negative.");
295+
this.x = x;
296+
this.y = y;
297+
this.width = width;
298+
this.height = height;
299+
}
300+
301+
public string ToString(string format, IFormatProvider formatProvider)
302+
{
303+
return "{0},{1},{2},{3}".Fmt(x, y, width, height);
304+
}
305+
306+
public static Rect Parse(string input)
307+
{
308+
var parts = input.Split(',');
309+
return new Rect(
310+
double.Parse(parts[0]),
311+
double.Parse(parts[1]),
312+
double.Parse(parts[2]),
313+
double.Parse(parts[3])
314+
);
315+
}
316+
}
284317
}

0 commit comments

Comments
 (0)