Skip to content

Commit 2c8080d

Browse files
authored
Improvements in Reflection (#173)
1 parent 6351203 commit 2c8080d

File tree

8 files changed

+240
-1
lines changed

8 files changed

+240
-1
lines changed

Tests/NFUnitTestClasses/UnitTestConstructorTest.cs

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,148 @@ public void Constructors64_Test()
362362
Assert.True(ConstructorsTestClass64.testMethod());
363363
}
364364

365+
[TestMethod]
366+
public void ConstructorName_01()
367+
{
368+
var classToTest = typeof(ClassWith3Constructors);
369+
370+
ConstructorInfo[] constructors = classToTest.GetConstructors();
371+
372+
Assert.Equal(3, constructors.Length, $"Expecting 3 constructors, got {constructors.Length}.");
373+
374+
foreach (ConstructorInfo constructorInfo in constructors)
375+
{
376+
Assert.Equal(constructorInfo.Name, ".ctor", $"Expecting '.ctor' as constructor name, but got: {constructorInfo.Name}");
377+
}
378+
}
379+
380+
[TestMethod]
381+
public void ConstructorName_02()
382+
{
383+
var classToTest = typeof(ConstructorsTestClass2);
384+
385+
ConstructorInfo[] constructors = classToTest.GetConstructors();
386+
387+
Assert.Equal(1, constructors.Length, $"Expecting 1 constructor, got {constructors.Length}.");
388+
389+
foreach (ConstructorInfo constructorInfo in constructors)
390+
{
391+
Assert.Equal(constructorInfo.Name, ".ctor", $"Expecting '.ctor' as constructor name, but got: {constructorInfo.Name}");
392+
}
393+
}
394+
395+
[TestMethod]
396+
public void ConstructorName_03()
397+
{
398+
// constructor without modifier
399+
var classToTest = typeof(ConstructorsTestClass3);
400+
401+
ConstructorInfo[] constructors = classToTest.GetConstructors();
402+
403+
Assert.Equal(0, constructors.Length, $"Didn't expecting any constructor, got {constructors.Length}.");
404+
}
405+
406+
[TestMethod]
407+
public void ConstructorName_04()
408+
{
409+
// internal constructor
410+
var classToTest = typeof(ConstructorsTestClass5);
411+
412+
ConstructorInfo[] constructors = classToTest.GetConstructors();
413+
414+
Assert.Equal(0, constructors.Length, $"Didn't expecting any constructor, got {constructors.Length}.");
415+
}
416+
417+
[TestMethod]
418+
public void ConstructorName_05()
419+
{
420+
// private constructor
421+
var classToTest = typeof(ConstructorsTestClass6);
422+
423+
ConstructorInfo[] constructors = classToTest.GetConstructors();
424+
425+
Assert.Equal(0, constructors.Length, $"Didn't expecting any constructor, got {constructors.Length}.");
426+
}
427+
428+
[TestMethod]
429+
public void ConstructorName_06()
430+
{
431+
// static constructor
432+
var classToTest = typeof(ConstructorsTestClass36);
433+
434+
ConstructorInfo[] constructors = classToTest.GetConstructors();
435+
436+
Assert.Equal(1, constructors.Length, $"Expecting 1 constructor, got {constructors.Length}.");
437+
438+
foreach (ConstructorInfo constructorInfo in constructors)
439+
{
440+
Assert.Equal(constructorInfo.Name, ".ctor", $"Expecting '.ctor' as constructor name, but got: {constructorInfo.Name}");
441+
}
442+
}
443+
444+
[TestMethod]
445+
public void ConstructorName_07()
446+
{
447+
// constructor for base class
448+
var classToTest = typeof(ConstructorsTestClass44_Base);
449+
450+
ConstructorInfo[] constructors = classToTest.GetConstructors();
451+
452+
Assert.Equal(1, constructors.Length, $"Expecting 1 constructor, got {constructors.Length}.");
453+
454+
foreach (ConstructorInfo constructorInfo in constructors)
455+
{
456+
Assert.Equal(constructorInfo.Name, ".ctor", $"Expecting '.ctor' as constructor name, but got: {constructorInfo.Name}");
457+
}
458+
}
459+
460+
[TestMethod]
461+
public void ConstructorName_08()
462+
{
463+
// constructor for derived class
464+
var classToTest = typeof(ConstructorsTestClass44);
465+
466+
ConstructorInfo[] constructors = classToTest.GetConstructors();
467+
468+
Assert.Equal(1, constructors.Length, $"Expecting 1 constructor, got {constructors.Length}.");
469+
470+
foreach (ConstructorInfo constructorInfo in constructors)
471+
{
472+
Assert.Equal(constructorInfo.Name, ".ctor", $"Expecting '.ctor' as constructor name, but got: {constructorInfo.Name}");
473+
}
474+
}
475+
476+
[TestMethod]
477+
public void ConstructorParametersInfo_01()
478+
{
479+
var classToTest = typeof(ClassWith3Constructors);
480+
481+
ConstructorInfo[] constructors = classToTest.GetConstructors();
482+
483+
// get ParameterInfo for 1st constructor
484+
ParameterInfo[] constructorParameters = constructors[0].GetParameters();
485+
486+
OutputHelper.WriteLine("Checking parameters for 1st constructor of ClassWith3Constructors");
487+
Assert.Equal(0, constructorParameters.Length, $"Expecting no parameters, got {constructorParameters.Length}.");
488+
489+
// get ParameterInfo for 2nd constructor
490+
constructorParameters = constructors[1].GetParameters();
491+
492+
Assert.Equal(1, constructorParameters.Length, $"Expecting 1 parameter, got {constructorParameters.Length}.");
493+
494+
OutputHelper.WriteLine("Checking parameters for 2nd constructor of ClassWith3Constructors");
495+
Assert.Equal(constructorParameters[0].ParameterType.ToString(), $"{typeof(int)}", $"Expecting parameter of type {typeof(int)}, got {constructorParameters[0].ParameterType}.");
496+
497+
// get ParameterInfo for 3rd constructor
498+
constructorParameters = constructors[2].GetParameters();
499+
500+
Assert.Equal(2, constructorParameters.Length, $"Expecting 2 parameters, got {constructorParameters.Length}.");
501+
502+
OutputHelper.WriteLine("Checking parameters for 3rd constructor of ClassWith3Constructors");
503+
Assert.Equal(constructorParameters[0].ParameterType.ToString(), $"{typeof(int)}", $"Expecting parameter of type {typeof(int)}, got {constructorParameters[0].ParameterType}.");
504+
Assert.Equal(constructorParameters[1].ParameterType.ToString(), $"{typeof(string)}", $"Expecting parameter of type {typeof(string)}, got {constructorParameters[0].ParameterType}.");
505+
}
506+
365507
//Constructors Test Classes
366508
class ConstructorsTestClass1
367509
{
@@ -1180,6 +1322,22 @@ public static bool testMethod()
11801322
}
11811323
}
11821324

1325+
class ConstructorsTestClass36
1326+
{
1327+
1328+
// static constructor
1329+
static ConstructorsTestClass36()
1330+
{
1331+
intI = 5;
1332+
}
1333+
1334+
static int intI = 1;
1335+
1336+
public static bool testMethod()
1337+
{
1338+
return (intI == 5);
1339+
}
1340+
}
11831341

11841342
class ConstructorsTestClass44_Base
11851343
{
@@ -1567,5 +1725,21 @@ public static bool testMethod()
15671725
return true;
15681726
}
15691727
}
1728+
1729+
public class ClassWith3Constructors
1730+
{
1731+
public int intValue = 0;
1732+
public string stringValue = "";
1733+
1734+
public ClassWith3Constructors() { }
1735+
1736+
public ClassWith3Constructors(int intValue) { this.intValue = intValue; }
1737+
1738+
public ClassWith3Constructors(int intValue, string stringValue)
1739+
{
1740+
this.intValue = intValue;
1741+
this.stringValue = stringValue;
1742+
}
1743+
}
15701744
}
15711745
}

nanoFramework.CoreLibrary/CoreLibrary.nfproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,7 @@
140140
<Compile Include="System\Reflection\AssemblyReflectionAttributes.cs" />
141141
<Compile Include="System\Reflection\Binder.cs" />
142142
<Compile Include="System\Reflection\BindingFlags.cs" />
143+
<Compile Include="System\Reflection\ParameterInfo.cs" />
143144
<Compile Include="System\Reflection\ConstructorInfo.cs" />
144145
<Compile Include="System\Reflection\CustomAttributesHelpers.cs" />
145146
<Compile Include="System\Reflection\DefaultMemberAttribute.cs" />

nanoFramework.CoreLibrary/System/AssemblyInfo.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,4 @@
1313
[assembly: AssemblyProduct(".NET nanoFramework mscorlib")]
1414
[assembly: AssemblyCopyright("Copyright (c) .NET Foundation and Contributors")]
1515

16-
[assembly: AssemblyNativeVersion("100.5.0.15")]
16+
[assembly: AssemblyNativeVersion("100.5.0.16")]

nanoFramework.CoreLibrary/System/Reflection/MethodBase.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ namespace System.Reflection
1818
[Serializable]
1919
public abstract class MethodBase : MemberInfo
2020
{
21+
// required to store native
22+
private int _token;
23+
2124
/// <summary>
2225
/// Gets a value indicating whether this is a public method.
2326
/// </summary>
@@ -78,6 +81,12 @@ public extern bool IsAbstract
7881
get;
7982
}
8083

84+
/// <summary>
85+
/// When overridden in a derived class, gets the parameters of the specified method or constructor.
86+
/// </summary>
87+
/// <returns>An array of type <see cref="ParameterInfo"/> containing information that matches the signature of the method (or constructor) reflected by this <see cref="MethodBase"/> instance.</returns>
88+
public abstract ParameterInfo[] GetParameters();
89+
8190
/// <summary>
8291
/// Invokes the method or constructor represented by the current instance, using the specified parameters.
8392
/// </summary>
@@ -114,6 +123,9 @@ public override extern Type DeclaringType
114123
[MethodImpl(MethodImplOptions.InternalCall)]
115124
get;
116125
}
126+
127+
[MethodImpl(MethodImplOptions.InternalCall)]
128+
internal extern ParameterInfo[] GetParametersNative();
117129
}
118130
}
119131

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//
2+
// Copyright (c) .NET Foundation and Contributors
3+
// Portions Copyright (c) Microsoft Corporation. All rights reserved.
4+
// See LICENSE file in the project root for full license information.
5+
//
6+
7+
#if NANOCLR_REFLECTION
8+
9+
namespace System.Reflection
10+
{
11+
using Runtime.CompilerServices;
12+
using System;
13+
14+
/// <summary>
15+
/// Discovers the attributes of a parameter and provides access to parameter metadata.
16+
/// </summary>
17+
/// <remarks>Available only in mscorlib build with support for System.Reflection.</remarks>
18+
[Serializable]
19+
public abstract class ParameterInfo
20+
{
21+
#pragma warning disable S3459 // required to fill in in native code
22+
private readonly Type _parameterType;
23+
#pragma warning restore S3459 // Unassigned members should be removed
24+
25+
/// <summary>
26+
/// Gets the <see cref="Type"/> of this parameter.
27+
/// </summary>
28+
/// <value>The <see cref="Type"/> object that represents the <see cref="Type"/> of this parameter.</value>
29+
public virtual Type ParameterType => _parameterType;
30+
}
31+
}
32+
33+
#endif // NANOCLR_REFLECTION

nanoFramework.CoreLibrary/System/Reflection/RuntimeConstructorInfo.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,15 @@
99
namespace System.Reflection
1010
{
1111
using System;
12+
using System.Runtime.CompilerServices;
1213

1314
[Serializable]
1415
internal sealed class RuntimeConstructorInfo : ConstructorInfo
1516
{
17+
public override ParameterInfo[] GetParameters()
18+
{
19+
return GetParametersNative();
20+
}
1621
}
1722
}
1823

nanoFramework.CoreLibrary/System/Reflection/RuntimeMethodInfo.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,11 @@ public override object[] GetCustomAttributes(bool inherit)
2525
return CustomAttributesHelpers.GetCustomAttributesInternal(GetCustomAttributesNative(inherit));
2626
}
2727

28+
public override ParameterInfo[] GetParameters()
29+
{
30+
return GetParametersNative();
31+
}
32+
2833
[MethodImpl(MethodImplOptions.InternalCall)]
2934
private extern object[] GetCustomAttributesNative(bool inherit);
3035
}

nanoFramework.CoreLibrary/System/Type.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,15 @@ public abstract Type BaseType
148148
[MethodImpl(MethodImplOptions.InternalCall)]
149149
public extern ConstructorInfo GetConstructor(Type[] types);
150150

151+
/// <summary>
152+
/// Returns all the public constructors defined for the current <see cref="Type"/>.
153+
/// </summary>
154+
/// <returns>
155+
/// An array of <see cref="ConstructorInfo"/> objects representing all the public instance constructors defined for the current <see cref="Type"/>, but not including the type initializer (static constructor). If no public instance constructors are defined for the current <see cref="Type"/>, or if the current <see cref="Type"/> represents a type parameter in the definition of a generic type or generic method, an empty array of type <see cref="ConstructorInfo"/> is returned.
156+
/// </returns>
157+
[MethodImpl(MethodImplOptions.InternalCall)]
158+
public extern ConstructorInfo[] GetConstructors();
159+
151160
/// <summary>
152161
/// Searches for the specified public method whose parameters match the specified argument types.
153162
/// </summary>

0 commit comments

Comments
 (0)