Skip to content

Commit

Permalink
rewrite constructor reflection to use same MetadataToken trick that i…
Browse files Browse the repository at this point in the history
…s being used for MethodReflection

implement MemberReflection.Transmute() and add associated extension methosd
Bump version number
add basic unit tests for memberReflection.Transmute()
  • Loading branch information
hannasm committed Jan 19, 2017
1 parent 3caccae commit a2c7954
Show file tree
Hide file tree
Showing 9 changed files with 92 additions and 12 deletions.
49 changes: 49 additions & 0 deletions ExpressiveReflection.Tests/MemberReflectionTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -351,5 +351,54 @@ public void Test027()

Assert.AreEqual(instance["DEF"], "GHI");
}

class TransmuteTestClass001<T>
{
public T GenericField;
public T GenericProperty { get; set; }
public string StringFIeld;
public string StringProperty { get; set; }
}

[TestMethod]
public void Test030()
{
var member = new MemberReflection();
var mi = member.From(() => default(TransmuteTestClass001<int>).GenericField);
var newMi = member.Transmute(mi, typeof(Guid));
var expectedMi = member.From(() => default(TransmuteTestClass001<Guid>).GenericField);

Assert.AreEqual(expectedMi, newMi);
}
[TestMethod]
public void Test031()
{
var member = new MemberReflection();
var mi = member.From(() => default(TransmuteTestClass001<int>).GenericProperty);
var newMi = member.Transmute(mi, typeof(Guid));
var expectedMi = member.From(() => default(TransmuteTestClass001<Guid>).GenericProperty);

Assert.AreEqual(expectedMi, newMi);
}
[TestMethod]
public void Test032()
{
var member = new MemberReflection();
var mi = member.From(() => default(TransmuteTestClass001<int>).StringFIeld);
var newMi = member.Transmute(mi, typeof(Guid));
var expectedMi = member.From(() => default(TransmuteTestClass001<Guid>).StringFIeld);

Assert.AreEqual(expectedMi, newMi);
}
[TestMethod]
public void Test033()
{
var member = new MemberReflection();
var mi = member.From(() => default(TransmuteTestClass001<int>).StringProperty);
var newMi = member.Transmute(mi, typeof(Guid));
var expectedMi = member.From(() => default(TransmuteTestClass001<Guid>).StringProperty);

Assert.AreEqual(expectedMi, newMi);
}
}
}
5 changes: 2 additions & 3 deletions ExpressiveReflection/ConstructorReflection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,9 @@ public ConstructorInfo Transmute(ConstructorInfo other, params Type[] newGeneric
return other;
}


var index = other.DeclaringType.GetConstructors().Select((c, i) => new { c, i }).Where(d => d.c == other).Select(d => d.i).Single();

var type = other.DeclaringType.GetGenericTypeDefinition().MakeGenericType(newGenericArgs);
var transmuted = type.GetConstructors()[index];
var transmuted = type.GetConstructors().Where(c => c.MetadataToken == other.MetadataToken).Single();
return transmuted;
}

Expand Down
Binary file modified ExpressiveReflection/ExpressiveReflection.Sources.nuspec
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,12 @@ public static void SetValue<T>(this MemberInfo member, object instance, T value,
public static void SetValue(this MemberInfo member, object instance, object value, params object[] args)
{
Reflection.SetValue(member, instance, value, args);
}

public static MemberInfo Transmute(this MemberInfo member, params Type[] newGenericArgs)
{
return Reflection.Transmute(member, newGenericArgs);
}

public static ConstructorInfo Transmute(this ConstructorInfo constructor, params Type[] newGenericArgs)
{
return Reflection.Transmute(constructor, newGenericArgs);
Expand Down
20 changes: 19 additions & 1 deletion ExpressiveReflection/MemberReflection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,25 @@ namespace ExpressiveReflection
public
#endif
class MemberReflection
{
{
/// <summary>
/// Convert a memberinfo from one generic type permutation to a different generic permutation. If you don't want to
/// transmute the declaring type, specify null / do not specify the newGenericArgs.
/// </summary>
public MemberInfo Transmute(MemberInfo target, params Type[] newGenericArgs)
{
// you can't transmute a non-generic type's constructor because there are no generic arguments
// to change
if (!target.DeclaringType.IsGenericType || newGenericArgs == null || newGenericArgs.Length == 0)
{
return target;
}

var type = target.DeclaringType.GetGenericTypeDefinition().MakeGenericType(newGenericArgs);
var transmuted = type.GetMembers().Where(m => m.MetadataToken == target.MetadataToken).Single();
return transmuted;
}

/// <summary>
/// Use expression tree to reflect property info from types
/// </summary>
Expand Down
4 changes: 3 additions & 1 deletion ExpressiveReflection/Package.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,16 @@
<package >
<metadata>
<id>ExpressiveReflection</id>
<version>1.3.1</version>
<version>1.3.2</version>
<authors>hannasm</authors>
<owners>hannasm</owners>
<licenseUrl>https://github.com/hannasm/ExpressiveReflectionDotnet/blob/master/LICENSE</licenseUrl>
<projectUrl>https://github.com/hannasm/ExpressiveReflectionDotnet</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Tools to simplify coding with the .NET reflection APIs.</description>
<releaseNotes>
* 1.3.2 - Implemented a MemberReflection.Transmute() method to complement the other Transmute() offerings
* 1.3.2 - rewrite constructorReflection.Transmute() to use same MetadataToken trick that the MethodReflection.Transmtue() relies on
* 1.3.1 - Fix for bug in MethodReflection.Transmute() leading to completely random method derivations being returned
* 1.3.1 - Fix for bug in ConstructorReflection.Transmute() leading to no transmute operation taking place
* 1.3.0 - added Transmute() methods for Constructors / Methods / Types allowing quick change of generic type arguments
Expand Down
4 changes: 2 additions & 2 deletions ExpressiveReflection/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.3.1")]
[assembly: AssemblyFileVersion("1.3.1")]
[assembly: AssemblyVersion("1.3.2")]
[assembly: AssemblyFileVersion("1.3.2")]
4 changes: 4 additions & 0 deletions ExpressiveReflection/Reflection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ public static string GetMemberName<T>(Expression<Func<T>> memberExpression)
{
return _member.NameOf(memberExpression);
}
public static MemberInfo Transmute(MemberInfo member, params Type[] newGenericArgs)
{
return _member.Transmute(member, newGenericArgs);
}

public static MethodInfo Transmute(MethodInfo other, Type[] typeArgsForType, Type[] typeArgsForMethod)
{
Expand Down
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# Versioning
This is version 1.3.1 of the expressive reflection library.
This is version 1.3.2 of the expressive reflection library.

This package is available from nuget at: https://www.nuget.org/packages/ExpressiveReflection/1.3.1
This package is available from nuget at: https://www.nuget.org/packages/ExpressiveReflection/1.3.2

This package is also available from nuget as an embeddable sources package at: https://www.nuget.org/packages/ExpressiveReflection.Sources/1.3.1
This package is also available from nuget as an embeddable sources package at: https://www.nuget.org/packages/ExpressiveReflection.Sources/1.3.2

The source for this release is available on github at: https://github.com/hannasm/ExpressiveReflectionDotNet/releases/tag/1.3.1
The source for this release is available on github at: https://github.com/hannasm/ExpressiveReflectionDotNet/releases/tag/1.3.2

# ExpressiveReflectionDotnet
This is a .NET library for simplifying reflection / metadata programming and making
Expand Down Expand Up @@ -49,6 +49,10 @@ The ExpressiveReflection.Reflection class exposes all of the reflection methods
There is a fairly comprehensive set of unit tests, and additionald examples demonstrating functionality can be found there.

# Changelog
## 1.3.2
* 1.3.2 - Implemented a MemberReflection.Transmute() method to complement the other Transmute() offerings
* 1.3.2 - rewrite constructorReflection.Transmute() to use same MetadataToken trick that the MethodReflection.Transmtue() relies on

## 1.3.1
* 1.3.1 - Fix for bug in MethodReflection.Transmute() leading to completely random method derivations being returned
* 1.3.1 - Fix for bug in ConstructorReflection.Transmute() leading to no transmute operation taking place
Expand Down

0 comments on commit a2c7954

Please sign in to comment.