Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improvements in Reflection #173

Merged
merged 1 commit into from
Jan 28, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
174 changes: 174 additions & 0 deletions Tests/NFUnitTestClasses/UnitTestConstructorTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,148 @@ public void Constructors64_Test()
Assert.True(ConstructorsTestClass64.testMethod());
}

[TestMethod]
public void ConstructorName_01()
{
var classToTest = typeof(ClassWith3Constructors);

ConstructorInfo[] constructors = classToTest.GetConstructors();

Assert.Equal(3, constructors.Length, $"Expecting 3 constructors, got {constructors.Length}.");

foreach (ConstructorInfo constructorInfo in constructors)
{
Assert.Equal(constructorInfo.Name, ".ctor", $"Expecting '.ctor' as constructor name, but got: {constructorInfo.Name}");
}
}

[TestMethod]
public void ConstructorName_02()
{
var classToTest = typeof(ConstructorsTestClass2);

ConstructorInfo[] constructors = classToTest.GetConstructors();

Assert.Equal(1, constructors.Length, $"Expecting 1 constructor, got {constructors.Length}.");

foreach (ConstructorInfo constructorInfo in constructors)
{
Assert.Equal(constructorInfo.Name, ".ctor", $"Expecting '.ctor' as constructor name, but got: {constructorInfo.Name}");
}
}

[TestMethod]
public void ConstructorName_03()
{
// constructor without modifier
var classToTest = typeof(ConstructorsTestClass3);

ConstructorInfo[] constructors = classToTest.GetConstructors();

Assert.Equal(0, constructors.Length, $"Didn't expecting any constructor, got {constructors.Length}.");
}

[TestMethod]
public void ConstructorName_04()
{
// internal constructor
var classToTest = typeof(ConstructorsTestClass5);

ConstructorInfo[] constructors = classToTest.GetConstructors();

Assert.Equal(0, constructors.Length, $"Didn't expecting any constructor, got {constructors.Length}.");
}

[TestMethod]
public void ConstructorName_05()
{
// private constructor
var classToTest = typeof(ConstructorsTestClass6);

ConstructorInfo[] constructors = classToTest.GetConstructors();

Assert.Equal(0, constructors.Length, $"Didn't expecting any constructor, got {constructors.Length}.");
}

[TestMethod]
public void ConstructorName_06()
{
// static constructor
var classToTest = typeof(ConstructorsTestClass36);

ConstructorInfo[] constructors = classToTest.GetConstructors();

Assert.Equal(1, constructors.Length, $"Expecting 1 constructor, got {constructors.Length}.");

foreach (ConstructorInfo constructorInfo in constructors)
{
Assert.Equal(constructorInfo.Name, ".ctor", $"Expecting '.ctor' as constructor name, but got: {constructorInfo.Name}");
}
}

[TestMethod]
public void ConstructorName_07()
{
// constructor for base class
var classToTest = typeof(ConstructorsTestClass44_Base);

ConstructorInfo[] constructors = classToTest.GetConstructors();

Assert.Equal(1, constructors.Length, $"Expecting 1 constructor, got {constructors.Length}.");

foreach (ConstructorInfo constructorInfo in constructors)
{
Assert.Equal(constructorInfo.Name, ".ctor", $"Expecting '.ctor' as constructor name, but got: {constructorInfo.Name}");
}
}

[TestMethod]
public void ConstructorName_08()
{
// constructor for derived class
var classToTest = typeof(ConstructorsTestClass44);

ConstructorInfo[] constructors = classToTest.GetConstructors();

Assert.Equal(1, constructors.Length, $"Expecting 1 constructor, got {constructors.Length}.");

foreach (ConstructorInfo constructorInfo in constructors)
{
Assert.Equal(constructorInfo.Name, ".ctor", $"Expecting '.ctor' as constructor name, but got: {constructorInfo.Name}");
}
}

[TestMethod]
public void ConstructorParametersInfo_01()
{
var classToTest = typeof(ClassWith3Constructors);

ConstructorInfo[] constructors = classToTest.GetConstructors();

// get ParameterInfo for 1st constructor
ParameterInfo[] constructorParameters = constructors[0].GetParameters();

OutputHelper.WriteLine("Checking parameters for 1st constructor of ClassWith3Constructors");
Assert.Equal(0, constructorParameters.Length, $"Expecting no parameters, got {constructorParameters.Length}.");

// get ParameterInfo for 2nd constructor
constructorParameters = constructors[1].GetParameters();

Assert.Equal(1, constructorParameters.Length, $"Expecting 1 parameter, got {constructorParameters.Length}.");

OutputHelper.WriteLine("Checking parameters for 2nd constructor of ClassWith3Constructors");
Assert.Equal(constructorParameters[0].ParameterType.ToString(), $"{typeof(int)}", $"Expecting parameter of type {typeof(int)}, got {constructorParameters[0].ParameterType}.");

// get ParameterInfo for 3rd constructor
constructorParameters = constructors[2].GetParameters();

Assert.Equal(2, constructorParameters.Length, $"Expecting 2 parameters, got {constructorParameters.Length}.");

OutputHelper.WriteLine("Checking parameters for 3rd constructor of ClassWith3Constructors");
Assert.Equal(constructorParameters[0].ParameterType.ToString(), $"{typeof(int)}", $"Expecting parameter of type {typeof(int)}, got {constructorParameters[0].ParameterType}.");
Assert.Equal(constructorParameters[1].ParameterType.ToString(), $"{typeof(string)}", $"Expecting parameter of type {typeof(string)}, got {constructorParameters[0].ParameterType}.");
}

//Constructors Test Classes
class ConstructorsTestClass1
{
Expand Down Expand Up @@ -1180,6 +1322,22 @@ public static bool testMethod()
}
}

class ConstructorsTestClass36
{

// static constructor
static ConstructorsTestClass36()
{
intI = 5;
}

static int intI = 1;

public static bool testMethod()
{
return (intI == 5);
}
}

class ConstructorsTestClass44_Base
{
Expand Down Expand Up @@ -1567,5 +1725,21 @@ public static bool testMethod()
return true;
}
}

public class ClassWith3Constructors
{
public int intValue = 0;
public string stringValue = "";

public ClassWith3Constructors() { }

public ClassWith3Constructors(int intValue) { this.intValue = intValue; }

public ClassWith3Constructors(int intValue, string stringValue)
{
this.intValue = intValue;
this.stringValue = stringValue;
}
}
}
}
1 change: 1 addition & 0 deletions nanoFramework.CoreLibrary/CoreLibrary.nfproj
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@
<Compile Include="System\Reflection\AssemblyReflectionAttributes.cs" />
<Compile Include="System\Reflection\Binder.cs" />
<Compile Include="System\Reflection\BindingFlags.cs" />
<Compile Include="System\Reflection\ParameterInfo.cs" />
<Compile Include="System\Reflection\ConstructorInfo.cs" />
<Compile Include="System\Reflection\CustomAttributesHelpers.cs" />
<Compile Include="System\Reflection\DefaultMemberAttribute.cs" />
Expand Down
2 changes: 1 addition & 1 deletion nanoFramework.CoreLibrary/System/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,4 @@
[assembly: AssemblyProduct(".NET nanoFramework mscorlib")]
[assembly: AssemblyCopyright("Copyright (c) .NET Foundation and Contributors")]

[assembly: AssemblyNativeVersion("100.5.0.15")]
[assembly: AssemblyNativeVersion("100.5.0.16")]
12 changes: 12 additions & 0 deletions nanoFramework.CoreLibrary/System/Reflection/MethodBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ namespace System.Reflection
[Serializable]
public abstract class MethodBase : MemberInfo
{
// required to store native
private int _token;

/// <summary>
/// Gets a value indicating whether this is a public method.
/// </summary>
Expand Down Expand Up @@ -78,6 +81,12 @@ public extern bool IsAbstract
get;
}

/// <summary>
/// When overridden in a derived class, gets the parameters of the specified method or constructor.
/// </summary>
/// <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>
public abstract ParameterInfo[] GetParameters();

/// <summary>
/// Invokes the method or constructor represented by the current instance, using the specified parameters.
/// </summary>
Expand Down Expand Up @@ -114,6 +123,9 @@ public override extern Type DeclaringType
[MethodImpl(MethodImplOptions.InternalCall)]
get;
}

[MethodImpl(MethodImplOptions.InternalCall)]
internal extern ParameterInfo[] GetParametersNative();
}
}

Expand Down
33 changes: 33 additions & 0 deletions nanoFramework.CoreLibrary/System/Reflection/ParameterInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//
// Copyright (c) .NET Foundation and Contributors
// Portions Copyright (c) Microsoft Corporation. All rights reserved.
// See LICENSE file in the project root for full license information.
//

#if NANOCLR_REFLECTION

namespace System.Reflection
{
using Runtime.CompilerServices;
using System;

/// <summary>
/// Discovers the attributes of a parameter and provides access to parameter metadata.
/// </summary>
/// <remarks>Available only in mscorlib build with support for System.Reflection.</remarks>
[Serializable]
public abstract class ParameterInfo
{
#pragma warning disable S3459 // required to fill in in native code
private readonly Type _parameterType;
#pragma warning restore S3459 // Unassigned members should be removed

/// <summary>
/// Gets the <see cref="Type"/> of this parameter.
/// </summary>
/// <value>The <see cref="Type"/> object that represents the <see cref="Type"/> of this parameter.</value>
public virtual Type ParameterType => _parameterType;
}
}

#endif // NANOCLR_REFLECTION
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,15 @@
namespace System.Reflection
{
using System;
using System.Runtime.CompilerServices;

[Serializable]
internal sealed class RuntimeConstructorInfo : ConstructorInfo
{
public override ParameterInfo[] GetParameters()
{
return GetParametersNative();
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ public override object[] GetCustomAttributes(bool inherit)
return CustomAttributesHelpers.GetCustomAttributesInternal(GetCustomAttributesNative(inherit));
}

public override ParameterInfo[] GetParameters()
{
return GetParametersNative();
}

[MethodImpl(MethodImplOptions.InternalCall)]
private extern object[] GetCustomAttributesNative(bool inherit);
}
Expand Down
9 changes: 9 additions & 0 deletions nanoFramework.CoreLibrary/System/Type.cs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,15 @@ public abstract Type BaseType
[MethodImpl(MethodImplOptions.InternalCall)]
public extern ConstructorInfo GetConstructor(Type[] types);

/// <summary>
/// Returns all the public constructors defined for the current <see cref="Type"/>.
/// </summary>
/// <returns>
/// 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.
/// </returns>
[MethodImpl(MethodImplOptions.InternalCall)]
public extern ConstructorInfo[] GetConstructors();

/// <summary>
/// Searches for the specified public method whose parameters match the specified argument types.
/// </summary>
Expand Down