From 4b6da75dfdf100810cbf13d9178e7a65924e7fb6 Mon Sep 17 00:00:00 2001 From: eeichinger Date: Wed, 22 Oct 2008 17:53:42 +0000 Subject: [PATCH] additional fix + tests for DynamicReflection (SPRNET-969) --- .../Dynamic/DynamicReflectionManager.cs | 10 + test/Spring/Spring.Core.Tests/CommonTypes.cs | 12 ++ .../Reflection/Dynamic/DynamicFieldTests.cs | 189 ++++++++++-------- .../Dynamic/DynamicPropertyTests.cs | 18 ++ 4 files changed, 145 insertions(+), 84 deletions(-) diff --git a/src/Spring/Spring.Core/Reflection/Dynamic/DynamicReflectionManager.cs b/src/Spring/Spring.Core/Reflection/Dynamic/DynamicReflectionManager.cs index c76ffeac..6320876a 100644 --- a/src/Spring/Spring.Core/Reflection/Dynamic/DynamicReflectionManager.cs +++ b/src/Spring/Spring.Core/Reflection/Dynamic/DynamicReflectionManager.cs @@ -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 ); diff --git a/test/Spring/Spring.Core.Tests/CommonTypes.cs b/test/Spring/Spring.Core.Tests/CommonTypes.cs index 68b894d7..b13b9e26 100644 --- a/test/Spring/Spring.Core.Tests/CommonTypes.cs +++ b/test/Spring/Spring.Core.Tests/CommonTypes.cs @@ -346,6 +346,18 @@ namespace Spring set { dob = value; } } + /// + /// R/W PlaceOfBirth property + /// + public Place POB + { + get { return pob; } + set { pob = value; } + } + + /// + /// Readonly + /// public Place PlaceOfBirth { get { return pob; } diff --git a/test/Spring/Spring.Core.Tests/Reflection/Dynamic/DynamicFieldTests.cs b/test/Spring/Spring.Core.Tests/Reflection/Dynamic/DynamicFieldTests.cs index 297f6deb..880cb7e7 100644 --- a/test/Spring/Spring.Core.Tests/Reflection/Dynamic/DynamicFieldTests.cs +++ b/test/Spring/Spring.Core.Tests/Reflection/Dynamic/DynamicFieldTests.cs @@ -30,18 +30,19 @@ using Spring.Context.Support; namespace Spring.Reflection.Dynamic { - /// + /// /// Unit tests for the DynamicField class. /// /// Aleksandar Seovic - [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 /// /// 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 - + } diff --git a/test/Spring/Spring.Core.Tests/Reflection/Dynamic/DynamicPropertyTests.cs b/test/Spring/Spring.Core.Tests/Reflection/Dynamic/DynamicPropertyTests.cs index a789751e..f7be0b70 100644 --- a/test/Spring/Spring.Core.Tests/Reflection/Dynamic/DynamicPropertyTests.cs +++ b/test/Spring/Spring.Core.Tests/Reflection/Dynamic/DynamicPropertyTests.cs @@ -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) { } + } } }