Skip to content

Commit eb5e32c

Browse files
authored
Add support for custom attributes with constructors for methods and and classes (#102)
***PUBLISH_RELEASE*** ***UPDATE_DEPENDENTS***
1 parent 3121bc2 commit eb5e32c

File tree

6 files changed

+72
-43
lines changed

6 files changed

+72
-43
lines changed

source/nanoFramework.CoreLibrary/CoreLibrary.nfproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@
129129
<Compile Include="System\Reflection\Binder.cs" />
130130
<Compile Include="System\Reflection\BindingFlags.cs" />
131131
<Compile Include="System\Reflection\ConstructorInfo.cs" />
132+
<Compile Include="System\Reflection\CustomAttributesHelpers.cs" />
132133
<Compile Include="System\Reflection\DefaultMemberAttribute.cs" />
133134
<Compile Include="System\Reflection\FieldInfo.cs" />
134135
<Compile Include="System\Reflection\FieldReflectionAttributes.cs" />

source/nanoFramework.CoreLibrary/System/AssemblyInfo.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@
1414
[assembly: AssemblyProduct("nanoFramework mscorlib")]
1515
[assembly: AssemblyCopyright("Copyright © nanoFramework Contributors 2017")]
1616

17-
[assembly: AssemblyNativeVersion("100.4.7.0")]
17+
[assembly: AssemblyNativeVersion("100.4.8.0")]
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
//
2+
// Copyright (c) 2020 The nanoFramework project contributors
3+
// See LICENSE file in the project root for full license information.
4+
//
5+
6+
namespace System.Reflection
7+
{
8+
internal class CustomAttributesHelpers
9+
{
10+
public static object[] GetCustomAttributesInternal(object[] rawAttributes)
11+
{
12+
// get the custom attributes data for the field
13+
// these are returned "encoded" in an object array with 2 positions for each attribute
14+
// 1st the attribute type
15+
// 2nd the constructor parameter or null, if the attribute has no constructor
16+
//
17+
// current limitations:
18+
// - works only for constructors with a single parameter
19+
// - the parameter has to be a string or numeric type
20+
//
21+
// both limitations above can be relatively easily overcome by adding the appropriate code at the native handler
22+
23+
object[] attributes = new object[rawAttributes.Length / 2];
24+
25+
for (int i = 0; i < rawAttributes.Length; i += 2)
26+
{
27+
// peek next element to determine if it's null
28+
if (rawAttributes[i + 1] == null)
29+
{
30+
// attribute without default constructor, just copy it
31+
attributes[i / 2] = rawAttributes[i];
32+
}
33+
else
34+
{
35+
// has default constructor, invoke it
36+
37+
// get the types
38+
Type objectType = rawAttributes[i].GetType();
39+
Type paramType = rawAttributes[i + 1].GetType();
40+
41+
// get constructor
42+
ConstructorInfo ctor = objectType.GetConstructor(new Type[] { paramType });
43+
44+
// invoke constructor with the parameter
45+
attributes[i / 2] = ctor.Invoke(new object[] { rawAttributes[i + 1] });
46+
}
47+
}
48+
49+
return attributes;
50+
}
51+
}
52+
}

source/nanoFramework.CoreLibrary/System/Reflection/FieldInfo.cs

Lines changed: 1 addition & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -73,45 +73,7 @@ public abstract Type FieldType
7373
/// <remarks>This method ignores the inherit parameter for properties and events.</remarks>
7474
public override object[] GetCustomAttributes(bool inherit)
7575
{
76-
// get the custom attributes data for the field
77-
// these are returned "encoded" in an object array with 2 positions for each attribute
78-
// 1st the attribute type
79-
// 2nd the constructor parameter or null, if the attribute has no constructor
80-
//
81-
// current limitations:
82-
// - works only for constructors with a single parameter
83-
// - the parameter has to be a string or numeric type
84-
//
85-
// both limitations above can be relatively easily overcome by adding the appropriate code at the native handler
86-
var ret = GetCustomAttributesNative(inherit);
87-
88-
object[] attributes = new object[ ret.Length/2 ];
89-
90-
for (int i = 0; i < ret.Length; i += 2)
91-
{
92-
// peek next element to determine if it's null
93-
if(ret[ i+1 ] == null)
94-
{
95-
// attribute without default constructor, just copy it
96-
attributes[ i/2 ] = ret[i];
97-
}
98-
else
99-
{
100-
// has default constructor, invoke it
101-
102-
// get the types
103-
Type objectType = ret[i].GetType();
104-
Type paramType = ret[ i+1 ].GetType();
105-
106-
// get constructor
107-
ConstructorInfo ctor = objectType.GetConstructor(new Type[] { paramType });
108-
109-
// invoke constructor with the parameter
110-
attributes[ i/2 ] = ctor.Invoke(new object[] { ret[ i+1 ] });
111-
}
112-
}
113-
114-
return attributes;
76+
return CustomAttributesHelpers.GetCustomAttributesInternal(GetCustomAttributesNative(inherit));
11577
}
11678

11779
[MethodImpl(MethodImplOptions.InternalCall)]

source/nanoFramework.CoreLibrary/System/Reflection/RuntimeMethodInfo.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,16 @@ public override extern Type ReturnType
1919
[MethodImpl(MethodImplOptions.InternalCall)]
2020
get;
2121
}
22-
22+
23+
public override object[] GetCustomAttributes(bool inherit)
24+
{
25+
return CustomAttributesHelpers.GetCustomAttributesInternal(GetCustomAttributesNative(inherit));
26+
}
27+
2328
[MethodImpl(MethodImplOptions.InternalCall)]
24-
public override extern object[] GetCustomAttributes(bool inherit);
29+
#pragma warning disable S4200 // Native methods should be wrapped
30+
private extern object[] GetCustomAttributesNative(bool inherit);
31+
#pragma warning restore S4200 // Native methods should be wrapped
2532
}
2633
}
2734

source/nanoFramework.CoreLibrary/System/RuntimeType.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,15 @@ public override extern Type BaseType
8383
[MethodImpl(MethodImplOptions.InternalCall)]
8484
public override extern Type GetElementType();
8585

86+
public override object[] GetCustomAttributes(bool inherit)
87+
{
88+
return CustomAttributesHelpers.GetCustomAttributesInternal(GetCustomAttributesNative(inherit));
89+
}
90+
8691
[MethodImpl(MethodImplOptions.InternalCall)]
87-
public override extern object[] GetCustomAttributes(bool inherit);
92+
#pragma warning disable S4200 // Native methods should be wrapped
93+
private extern object[] GetCustomAttributesNative(bool inherit);
94+
#pragma warning restore S4200 // Native methods should be wrapped
8895
}
8996
}
9097

0 commit comments

Comments
 (0)