PrivateObject ignoring integer argument if it is 0
-
16 марта 2012 г. 14:35
I ran into a strange problem with PrivateObject that seems to ignore an integer argument given to the Invoke call if the value is "0". See the basic example below:
using System; using System.Reflection; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace TestProject1 { [TestClass] public class UnitTest1 { [TestMethod] public void TestMethod1() { var sut = new MyClass(); var sutPrivate = new PrivateObject(sut); // Passes: Assert.AreEqual(1, (int)sutPrivate.Invoke("MyMethod", 1)); // MissingMethodException: Assert.AreEqual(0, (int)sutPrivate.Invoke("MyMethod", 0)); // MissingMethodException: Assert.AreEqual(0, (int)sutPrivate.Invoke("MyMethod", new [] {typeof(UInt32)}, 0)); // Passes! Assert.AreEqual(0, (int)sutPrivate.Invoke("MyMethod", BindingFlags.NonPublic | BindingFlags.Instance, 0)); } } internal class MyClass { private int MyMethod(int arg) { return arg; } } }Note that the first invoke works as expected because the integer argument is "1". Second one fails with MissingMethodException and it doesn't even help to specify a type array as is done in the third attempt. Strangely it helps to specify BindingFlags.NonPublic and BindingFlags.Instance, which should be giving by using PrivateObject. Looking at the IL code I can see that the compiler omits the argument completely so MissingMethodException happens for a reason.
This seems like an error in the Invoke overload on PrivateObject or in the underlaying reflection calls, or have I missed something?
Tore Østergaard
Oticon A/S, Denmark
Все ответы
-
20 марта 2012 г. 7:35Модератор
Hi Tore,
Thank you for posting in the MSDN forum.
I try to repro this issue. Then I use the tool .NET Reflector to check it
1)Assert.AreEqual(0, (int)sutPrivate.Invoke("MyMethod", (object)0));
Result: Failed
I get the result like the following screen shot with that tool.
2)Assert.AreEqual(1, (int)sutPrivate.Invoke("MyMethod", 1));
See:
Result: Passed
3)Assert.AreEqual(0, (int)sutPrivate.Invoke("MyMethod", (object)0));
Result: Passed
4)int i = 0;
Assert.AreEqual(0, sutPrivate.Invoke("MyMethod", i));
Result: Passed
As my understanding that if we use the step1 with 0, we just get an array like the object[0], it has the return value, but it could be the int or double or others, I think it is related to the Boxing and Unboxing, see http://msdn.microsoft.com/en-us/library/yz2be5wk(v=vs.100).aspx.
So if possible, use the workaround provided by us, hope it helps.
Best Regards,
Jack Zhai [MSFT]
MSDN Community Support | Feedback to us
-
20 марта 2012 г. 12:00
Thank you for your reply Jack.
Your solution 4 does indeed work, but put a "const" keyword in front of the declaration of the i variable (which Resharper will help you remember) and you get back into the MissingMethodException.
I think that I will use the boxing workaround, but I still think that it is a bug somewhere in the framework since I can work around it by using another overload to the Invoke method.
Tore Østergaard
Oticon A/S, Denmark -
21 марта 2012 г. 2:03Модератор
Hi Tore,
Glad to receive your reply.J
As my understanding, it is related to the Boxing and Unboxing. But if you think it is a feedback, you can submit this feedback to Microsoft Connect feedback portal: http://connect.microsoft.com, Microsoft engineers will evaluate them seriously. Thanks for your understanding.
Best Regards,
Jack Zhai [MSFT]
MSDN Community Support | Feedback to us
- Предложено в качестве ответа Jack Zhai - MSFTMicrosoft Contingent Staff, Moderator 22 марта 2012 г. 2:22
- Помечено в качестве ответа 2re 22 марта 2012 г. 13:39
-
21 марта 2012 г. 12:19I have created a Microsoft Connect feedback ticket: http://connect.microsoft.com/VisualStudio/feedback/details/732374/zero-integer-argument-is-seen-as-empty-array
Tore Østergaard
Oticon A/S, Denmark

