additional fix + tests for DynamicReflection (SPRNET-969)
This commit is contained in:
@@ -419,11 +419,17 @@ namespace Spring.Reflection.Dynamic
|
||||
{
|
||||
EmitTarget( il, fieldInfo.DeclaringType, isInstanceMethod );
|
||||
}
|
||||
|
||||
il.Emit( OpCodes.Ldarg_1 );
|
||||
if (fieldInfo.FieldType.IsValueType)
|
||||
{
|
||||
EmitUnbox( il, fieldInfo.FieldType );
|
||||
}
|
||||
else
|
||||
{
|
||||
il.Emit( OpCodes.Castclass, fieldInfo.FieldType );
|
||||
}
|
||||
|
||||
if (fieldInfo.IsStatic)
|
||||
{
|
||||
il.Emit( OpCodes.Stsfld, fieldInfo );
|
||||
@@ -490,6 +496,10 @@ namespace Spring.Reflection.Dynamic
|
||||
{
|
||||
EmitUnbox( il, propertyInfo.PropertyType );
|
||||
}
|
||||
else
|
||||
{
|
||||
il.Emit( OpCodes.Castclass, propertyInfo.PropertyType );
|
||||
}
|
||||
|
||||
// call setter
|
||||
EmitCall( il, method );
|
||||
|
||||
@@ -346,6 +346,18 @@ namespace Spring
|
||||
set { dob = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// R/W PlaceOfBirth property
|
||||
/// </summary>
|
||||
public Place POB
|
||||
{
|
||||
get { return pob; }
|
||||
set { pob = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Readonly
|
||||
/// </summary>
|
||||
public Place PlaceOfBirth
|
||||
{
|
||||
get { return pob; }
|
||||
|
||||
@@ -30,18 +30,19 @@ using Spring.Context.Support;
|
||||
|
||||
namespace Spring.Reflection.Dynamic
|
||||
{
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Unit tests for the DynamicField class.
|
||||
/// </summary>
|
||||
/// <author>Aleksandar Seovic</author>
|
||||
[TestFixture]
|
||||
[TestFixture]
|
||||
public class DynamicFieldTests
|
||||
{
|
||||
private const BindingFlags BINDANY = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;
|
||||
protected Inventor tesla;
|
||||
protected Inventor pupin;
|
||||
protected Society ieee;
|
||||
|
||||
#region SetUp and TearDown
|
||||
#region SetUp and TearDown
|
||||
|
||||
/// <summary>
|
||||
/// The setup logic executed before the execution of each individual test.
|
||||
@@ -50,7 +51,7 @@ namespace Spring.Reflection.Dynamic
|
||||
public void SetUp()
|
||||
{
|
||||
ContextRegistry.Clear();
|
||||
tesla = new Inventor("Nikola Tesla", new DateTime(1856, 7, 9), "Serbian");
|
||||
tesla = new Inventor( "Nikola Tesla", new DateTime( 1856, 7, 9 ), "Serbian" );
|
||||
tesla.Inventions = new string[]
|
||||
{
|
||||
"Telephone repeater", "Rotating magnetic field principle",
|
||||
@@ -60,99 +61,119 @@ namespace Spring.Reflection.Dynamic
|
||||
};
|
||||
tesla.PlaceOfBirth.City = "Smiljan";
|
||||
|
||||
pupin = new Inventor("Mihajlo Pupin", new DateTime(1854, 10, 9), "Serbian");
|
||||
pupin = new Inventor( "Mihajlo Pupin", new DateTime( 1854, 10, 9 ), "Serbian" );
|
||||
pupin.Inventions = new string[] { "Long distance telephony & telegraphy", "Secondary X-Ray radiation", "Sonar" };
|
||||
pupin.PlaceOfBirth.City = "Idvor";
|
||||
pupin.PlaceOfBirth.Country = "Serbia";
|
||||
|
||||
ieee = new Society();
|
||||
ieee.Members.Add(tesla);
|
||||
ieee.Members.Add(pupin);
|
||||
ieee.Members.Add( tesla );
|
||||
ieee.Members.Add( pupin );
|
||||
ieee.Officers["president"] = pupin;
|
||||
ieee.Officers["advisors"] = new Inventor[] { tesla, pupin }; // not historically accurate, but I need an array in the map ;-)
|
||||
}
|
||||
|
||||
|
||||
[TestFixtureTearDown]
|
||||
public void TearDown()
|
||||
{
|
||||
//DynamicReflectionManager.SaveAssembly();
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
protected virtual IDynamicField Create(FieldInfo field)
|
||||
{
|
||||
return DynamicField.Create(field);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestInstanceFields()
|
||||
protected virtual IDynamicField Create( FieldInfo field )
|
||||
{
|
||||
IDynamicField name = Create(typeof(Inventor).GetField("Name"));
|
||||
Assert.AreEqual(tesla.Name, name.GetValue(tesla));
|
||||
name.SetValue(tesla, "Tesla, Nikola");
|
||||
Assert.AreEqual("Tesla, Nikola", tesla.Name);
|
||||
Assert.AreEqual("Tesla, Nikola", name.GetValue(tesla));
|
||||
|
||||
MyStruct myYearHolder = new MyStruct();
|
||||
myYearHolder.Year = 2004;
|
||||
IDynamicField year = Create(typeof(MyStruct).GetField("year", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static));
|
||||
Assert.AreEqual(2004, year.GetValue(myYearHolder));
|
||||
return DynamicField.Create( field );
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException(typeof(InvalidOperationException))]
|
||||
public void TestInstanceFields()
|
||||
{
|
||||
IDynamicField name = Create( typeof( Inventor ).GetField( "Name" ) );
|
||||
Assert.AreEqual( tesla.Name, name.GetValue( tesla ) );
|
||||
name.SetValue( tesla, "Tesla, Nikola" );
|
||||
Assert.AreEqual( "Tesla, Nikola", tesla.Name );
|
||||
Assert.AreEqual( "Tesla, Nikola", name.GetValue( tesla ) );
|
||||
|
||||
MyStruct myYearHolder = new MyStruct();
|
||||
myYearHolder.Year = 2004;
|
||||
IDynamicField year = Create( typeof( MyStruct ).GetField( "year", BINDANY ) );
|
||||
Assert.AreEqual( 2004, year.GetValue( myYearHolder ) );
|
||||
}
|
||||
|
||||
[Test]
|
||||
[ExpectedException( typeof( InvalidOperationException ) )]
|
||||
public void TestAttemptingToSetFieldOfValueTypeInstance()
|
||||
{
|
||||
MyStruct myYearHolder = new MyStruct();
|
||||
IDynamicField year = Create(typeof(MyStruct).GetField("year"));
|
||||
year.SetValue(myYearHolder, 2004);
|
||||
IDynamicField year = Create( typeof( MyStruct ).GetField( "year" ) );
|
||||
year.SetValue( myYearHolder, 2004 );
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
||||
[Test]
|
||||
public void TestStaticFieldsOfClass()
|
||||
{
|
||||
IDynamicField myField = Create(typeof(MyStaticClass).GetField("myField"));
|
||||
myField.SetValue(null, "here we go...");
|
||||
IDynamicField myField = Create( typeof( MyStaticClass ).GetField( "myField" ) );
|
||||
myField.SetValue( null, "here we go..." );
|
||||
|
||||
IDynamicField myConst = Create(typeof(MyStaticClass).GetField("MyConst"));
|
||||
Assert.AreEqual(3456, myConst.GetValue(null));
|
||||
try {
|
||||
myConst.SetValue(null, 7890);
|
||||
IDynamicField myConst = Create( typeof( MyStaticClass ).GetField( "MyConst" ) );
|
||||
Assert.AreEqual( 3456, myConst.GetValue( null ) );
|
||||
try
|
||||
{
|
||||
myConst.SetValue( null, 7890 );
|
||||
}
|
||||
catch(InvalidOperationException){}
|
||||
catch (InvalidOperationException) { }
|
||||
|
||||
IDynamicField myReadonlyField = Create(typeof(MyStaticClass).GetField("myReadonlyField"));
|
||||
Assert.AreEqual("hohoho", myReadonlyField.GetValue(null));
|
||||
try {
|
||||
myReadonlyField.SetValue(null, "some other string");
|
||||
IDynamicField myReadonlyField = Create( typeof( MyStaticClass ).GetField( "myReadonlyField" ) );
|
||||
Assert.AreEqual( "hohoho", myReadonlyField.GetValue( null ) );
|
||||
try
|
||||
{
|
||||
myReadonlyField.SetValue( null, "some other string" );
|
||||
}
|
||||
catch(InvalidOperationException){}
|
||||
catch (InvalidOperationException) { }
|
||||
}
|
||||
|
||||
[Test]
|
||||
[Test]
|
||||
public void TestStaticFieldsOfStruct()
|
||||
{
|
||||
// static readonly
|
||||
IDynamicField maxValue = Create(typeof(DateTime).GetField("MaxValue"));
|
||||
Assert.AreEqual(DateTime.MaxValue, maxValue.GetValue(null));
|
||||
try {
|
||||
maxValue.SetValue(null, DateTime.Now);
|
||||
IDynamicField maxValue = Create( typeof( DateTime ).GetField( "MaxValue" ) );
|
||||
Assert.AreEqual( DateTime.MaxValue, maxValue.GetValue( null ) );
|
||||
try
|
||||
{
|
||||
maxValue.SetValue( null, DateTime.Now );
|
||||
}
|
||||
catch(InvalidOperationException){}
|
||||
catch (InvalidOperationException) { }
|
||||
|
||||
// const
|
||||
IDynamicField int64max = Create(typeof(Int64).GetField("MaxValue", BindingFlags.Public | BindingFlags.Static));
|
||||
Assert.AreEqual(Int64.MaxValue, int64max.GetValue(null));
|
||||
try {
|
||||
int64max.SetValue(null, 0);
|
||||
IDynamicField int64max = Create( typeof( Int64 ).GetField( "MaxValue", BindingFlags.Public | BindingFlags.Static ) );
|
||||
Assert.AreEqual( Int64.MaxValue, int64max.GetValue( null ) );
|
||||
try
|
||||
{
|
||||
int64max.SetValue( null, 0 );
|
||||
}
|
||||
catch(InvalidOperationException){}
|
||||
catch (InvalidOperationException) { }
|
||||
|
||||
// pure static
|
||||
IDynamicField myField = Create(typeof(MyStaticStruct).GetField("staticYear"));
|
||||
myField.SetValue(null, 2008);
|
||||
Assert.AreEqual(2008, myField.GetValue(null));
|
||||
IDynamicField myField = Create( typeof( MyStaticStruct ).GetField( "staticYear" ) );
|
||||
myField.SetValue( null, 2008 );
|
||||
Assert.AreEqual( 2008, myField.GetValue( null ) );
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSetIncompatibleType()
|
||||
{
|
||||
IDynamicField inventorPlace = Create( typeof( Inventor ).GetField( "pob", BINDANY ) );
|
||||
try { inventorPlace.SetValue( new Inventor(), new object() ); Assert.Fail(); }
|
||||
catch (InvalidCastException) { }
|
||||
try { inventorPlace.SetValue( new Inventor(), new DateTime() ); Assert.Fail(); }
|
||||
catch (InvalidCastException) { }
|
||||
|
||||
IDynamicField inventorDOB = Create( typeof( Inventor ).GetField( "dob", BINDANY ) );
|
||||
try { inventorDOB.SetValue( new Inventor(), 2 ); Assert.Fail(); }
|
||||
catch (InvalidCastException) { }
|
||||
try { inventorDOB.SetValue( new Inventor(), new Place() ); Assert.Fail(); }
|
||||
catch (InvalidCastException) { }
|
||||
}
|
||||
|
||||
#region Performance tests
|
||||
@@ -172,25 +193,25 @@ namespace Spring.Reflection.Dynamic
|
||||
x = tesla.Name;
|
||||
}
|
||||
stop = DateTime.Now;
|
||||
PrintTest("tesla.Name (direct)", n, Elapsed);
|
||||
PrintTest( "tesla.Name (direct)", n, Elapsed );
|
||||
|
||||
start = DateTime.Now;
|
||||
IDynamicField placeOfBirth = Create(typeof(Inventor).GetField("Name"));
|
||||
IDynamicField placeOfBirth = Create( typeof( Inventor ).GetField( "Name" ) );
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
x = placeOfBirth.GetValue(tesla);
|
||||
x = placeOfBirth.GetValue( tesla );
|
||||
}
|
||||
stop = DateTime.Now;
|
||||
PrintTest("tesla.Name (dynamic reflection)", n, Elapsed);
|
||||
PrintTest( "tesla.Name (dynamic reflection)", n, Elapsed );
|
||||
|
||||
start = DateTime.Now;
|
||||
FieldInfo placeOfBirthFi = typeof(Inventor).GetField("Name");
|
||||
FieldInfo placeOfBirthFi = typeof( Inventor ).GetField( "Name" );
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
x = placeOfBirthFi.GetValue(tesla);
|
||||
x = placeOfBirthFi.GetValue( tesla );
|
||||
}
|
||||
stop = DateTime.Now;
|
||||
PrintTest("tesla.Name (standard reflection)", n, Elapsed);
|
||||
PrintTest( "tesla.Name (standard reflection)", n, Elapsed );
|
||||
}
|
||||
|
||||
private double Elapsed
|
||||
@@ -198,69 +219,69 @@ namespace Spring.Reflection.Dynamic
|
||||
get { return (stop.Ticks - start.Ticks) / 10000000f; }
|
||||
}
|
||||
|
||||
private void PrintTest(string name, int iterations, double duration)
|
||||
private void PrintTest( string name, int iterations, double duration )
|
||||
{
|
||||
Debug.WriteLine(String.Format("{0,-60} {1,12:#,###} {2,12:##0.000} {3,12:#,###}", name, iterations, duration, iterations / duration));
|
||||
Debug.WriteLine( String.Format( "{0,-60} {1,12:#,###} {2,12:##0.000} {3,12:#,###}", name, iterations, duration, iterations / duration ) );
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
|
||||
#region IL generation helper classes (they help if you look at them in Reflector ;-)
|
||||
|
||||
public class ValueTypeField : IDynamicField
|
||||
{
|
||||
public object GetValue(object target)
|
||||
public object GetValue( object target )
|
||||
{
|
||||
return ((Inventor) target).Name;
|
||||
return ((Inventor)target).Name;
|
||||
}
|
||||
|
||||
public void SetValue(object target, object value)
|
||||
public void SetValue( object target, object value )
|
||||
{
|
||||
((Inventor)target).Name = (string) value;
|
||||
((Inventor)target).Name = (string)value;
|
||||
}
|
||||
}
|
||||
|
||||
public class ValueTypeTargetField : IDynamicField
|
||||
{
|
||||
public object GetValue(object target)
|
||||
public object GetValue( object target )
|
||||
{
|
||||
return ((MyStruct) target).year;
|
||||
return ((MyStruct)target).year;
|
||||
}
|
||||
|
||||
public void SetValue(object target, object value)
|
||||
public void SetValue( object target, object value )
|
||||
{
|
||||
MyStruct o = (MyStruct) target;
|
||||
o.Year = (int) value;
|
||||
MyStruct o = (MyStruct)target;
|
||||
o.Year = (int)value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class StaticField : IDynamicField
|
||||
{
|
||||
public object GetValue(object target)
|
||||
public object GetValue( object target )
|
||||
{
|
||||
return MyStaticClass.myField;
|
||||
}
|
||||
|
||||
public void SetValue(object target, object value)
|
||||
public void SetValue( object target, object value )
|
||||
{
|
||||
MyStaticClass.myField = (string) value;
|
||||
MyStaticClass.myField = (string)value;
|
||||
}
|
||||
}
|
||||
|
||||
public class StaticConst : IDynamicField
|
||||
{
|
||||
public object GetValue(object target)
|
||||
public object GetValue( object target )
|
||||
{
|
||||
return MyStaticClass.MyConst;
|
||||
}
|
||||
|
||||
public void SetValue(object target, object value)
|
||||
public void SetValue( object target, object value )
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -40,6 +40,8 @@ namespace Spring.Reflection.Dynamic
|
||||
[TestFixture]
|
||||
public class DynamicPropertyTests : BasePropertyTests
|
||||
{
|
||||
private const BindingFlags BINDANY = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;
|
||||
|
||||
protected override IDynamicProperty Create( PropertyInfo property )
|
||||
{
|
||||
return DynamicProperty.Create( property );
|
||||
@@ -80,5 +82,21 @@ namespace Spring.Reflection.Dynamic
|
||||
Create( typeof( DateTime ).GetProperty( "Today" ) );
|
||||
nonWritableProperty.SetValue( null, null );
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSetIncompatibleType()
|
||||
{
|
||||
IDynamicProperty inventorPlace = Create( typeof( Inventor ).GetProperty("POB") );
|
||||
try { inventorPlace.SetValue( new Inventor(), new object() ); Assert.Fail(); }
|
||||
catch (InvalidCastException) { }
|
||||
try { inventorPlace.SetValue( new Inventor(), new DateTime() ); Assert.Fail(); }
|
||||
catch (InvalidCastException) { }
|
||||
|
||||
IDynamicProperty inventorDOB = Create( typeof( Inventor ).GetProperty("DOB") );
|
||||
try { inventorDOB.SetValue( new Inventor(), 2 ); Assert.Fail(); }
|
||||
catch (InvalidCastException) { }
|
||||
try { inventorDOB.SetValue( new Inventor(), new Place() ); Assert.Fail(); }
|
||||
catch (InvalidCastException) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user