Want to show your appreciation?
Please a cup of tea.
Showing posts with label Reflection. Show all posts
Showing posts with label Reflection. Show all posts

Wednesday, November 04, 2009

Unit Test Value Object – Reusable Test Fixture

To Test Or Not Test

Shall I unit test value object? Here are some arguments that I found when googling for an answer to the question.

  1. Value object are so simple that you don’t need to test them.
  2. Test value object is tedious, basically copy and pasting and you can make the same mistake that you did in the value object itself.
  3. If you test every other part of the application, you would have tested your value object.

And there are also opposite opinions.

  1. Value objects are not as simple as you thought. How about initial property value, equals, hashcode and cloneable? (Yes, that reminds me that I made quite some mistakes in value objects)
  2. Unit test is tedious in nature. Tedious is not a reason for not doing it. But it only means that we need to find a better way.
  3. This is about unit testing, not integration testing. Value object is a unit that should be tested alone.

In summary, value objects are relatively simple so that the cost of manually writing test cases for them are too high to justify the benefit but not testing them leaving potential bugs.

The Reusable Test Fixture

Compromising the quality is a no in my book so the solution is to develop reusable tests to replace the repetitive and tedious work. This is what programmers are good at after all!

Let’s take a look at a very simple value object.

public class Foo
{
    public int Id { get; set; }
 
    public string StringProperty { get; set; }
 
    public long LongProperty { get; set; }
}

Writing a unit test for this class manually is plain boring. I should be able just do it in one line with a reusable test fixture.

[TestFixture] public void FooTest : SomeMagicReusableTestFixture<Foo> {}

This magic reusable test fixture is called NewableValueObjectTestFixture. It sets each property with a few (three minimal) values and read it back to make sure it gets the same value previously set. Of course, it does much more then just that…

Default Property Value

The above example is probably too simple. What if my property has default value? say the Id property is initialized to –1. No problem! The reusable test fixture also verifies the initial value of properties too. It expects all the properties are initialized to the default value of the type, or a value specified by DefaultValueAttribute.

The code below will fail the test because the the default value for int type is 0, not –1.

    private int _id = -1;
 
    public int Id
    {
        get { return _id; }
        set { _id = value; }
    }

If you intended to initialized to –1, you should tell this to the test fixture. The information is also useful to other .Net tools.

    private int _id = -1;
 
    [DefaultValue(-1)]
    public int Id
    {
        get { return _id; }
        set { _id = value; }
    }

The code above passes the test happily.

Equals and GetHashCode

NewableValueObjectTestFixture and its brother ValueObjectTestFixture test the Equals and GetHashCode methods too. They basically ensure that:

  1. The value object does not equals to null.
  2. The value object does not equals an arbitrary object (new object()).
  3. The value object equals to itself.
  4. The value objects are not equal if any one of their properties are not equal.
  5. When two value objects have same property values and Equals method returns true. The GetHashCode methods must return same value.

The implementation in the Object class complies to the above rules so the your value object passes the tests by default. But if you decide to override any of them, the test helps to ensure you have implemented Equals and GetHashCode properly, otherwise the test will fail. Below is generated by Resharper and it passes the test.

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (obj.GetType() != typeof(Foo)) return false;
        return Equals((Foo)obj);
    }
 
    public bool Equals(Foo other)
    {
        if (ReferenceEquals(null, other)) return false;
        if (ReferenceEquals(this, other)) return true;
        return other._id == _id &&
            Equals(other.StringProperty, StringProperty) &&
            other.LongProperty == LongProperty;
    }
 
    public override int GetHashCode()
    {
        unchecked
        {
            int result = _id;
            result = (result * 397) ^ (StringProperty != null ? StringProperty.GetHashCode() : 0);
            result = (result * 397) ^ LongProperty.GetHashCode();
            return result;
        }
    }

A few days later if I add another property to the Foo class and forget to added it to the Equals method, the test fixture will effectively catch it and fails the test. This is exactly what I wanted, how many times did I forget this?

Cloneable

If my value object implements ICloneable, the test fixture will help to check that as well. It clones the object and test all readable properties to make sure the cloned one has the same property values. Below is my typical clone implementation and it works well with the test fixture.

public class Foo : ICloneable
{
    public int Id { get; set; }
 
    public string StringProperty { get; set; }
 
    public long LongProperty { get; set; }
 
    object ICloneable.Clone()
    {
        return Clone();
    }
 
    public Foo Clone()
    {
        return (Foo)MemberwiseClone();
    }
}

Type of Property

Since the test fixture needs to generate test data, it had limited support for the type of the properties. For example, a property of interface type would be difficult for ValueObjectTestFixture to create test data of it.

Although, out of the box, ValueObjectTestFixture only support properties of c# build-in data types plus DateTime and TimeSpan, but it provides two extension mechanisms. You can either use a mock framework to generate mock objects for interface type and class type, or override the TestData method to provide your own test data for types that are not supported by the default implementation. Of course, nothing prevents you from making mixed use of both mechanisms.

Future enhancement may have ValueObjectTestFixture support enum, concrete class and/or maybe struct.

Using Mock Framework to Generate Test Data

ValueObjectTestFixture accepts an IMockTestDataProvider instance. I have included an implementation using RhinoMocks. But you can easily do the same using any other mock frameworks. RhinoMockTestDataProvider mocks any interfaces, or classes that are not sealed and has a default constructor. We may be able to remove the requirement of a default constructor in future but for now that is it. :)

Take a look at below value object:

public class ValueObject
{
    public IList<string> StringIList { get; set; }
 
    public List<TimeSpan> TimeSpanList { get; set; }
 
    public ICollection<int> IntICollection { get; set; }
 
    public IDictionary<string, object> StringObjectIDictrionary { get; set; }
 
    public Dictionary<int, DateTime> IntDataTimeDictionary { get; set; }
 
    public Component Component { get; set; }
 
    // other properties, equals, hash code, clone and etc.
}

To test this, the test class is as simple as below:

    [TestFixture]
    public class MockProviderTest : NewableValueObjectTestFixture<ValueObject>
    {
        public MockProviderTest()
        {
            MockProvider = new RhinoMockTestDataProvider();
        }
    }

The complete example can be found in Google code: MockProviderTest.cs

Provide Your Own Test Data

If you have property type that is neither supported out-of-box, nor by a mock framework. You can always provide it yourself by overriding the method TestData. Below is an example from CustomTest.cs:

        protected override IEnumerable TestData(PropertyInfo property)
        {
            // ValueObjectTestFixture doesn't support enum at this moment
            // so we have to provide our own test data.
            if (property.PropertyType == typeof(Operation))
            {
                return new[]
                           {
                               Operation.Subtraction, 
                               new Operation(), 
                               Operation.Addition, 
                               Operation.Muiplication, 
                               Operation.Division
                           };
            }
            return base.TestData(property);
        }

Extensibility

While ValueObjectTestFixture makes simple things simpler, it ensures complex things possible too. Here are some additional features that will come handy when testing not so simple value objects.

Value Object without Default Constructor

What if the value object doesn’t have a default constructor? No problem, have the test case inherit from ValueObjectTestFixture. The only difference between ValueObjectTestFixture and NewableValueObjectTestFixture is that the former forces you to override an abstract method: NewValueObject, which you are required to return a new instance of the value object under test. Below example is from CustomTest.cs:

        protected override CustomObject NewValueObject()
        {
            return new CustomObject("TestObject");
        }

Test Special Properties Myself

There are times that value object has non-simple properties. For example, when a read only property is initialized by the constructor:

public class CustomObject
{
    private readonly string _name;
    public CustomObject(string name)
    {
        _name = name;
    }
 
    public string Name { get { return _name; } }
}

Or, when a property is calculated from others:

public int Result
{
    get
    {
        switch (Operation)
        {
            case Operation.Addition:
                return LeftOperand + RightOperand;
            case Operation.Subtraction:
                return LeftOperand - RightOperand;
            case Operation.Muiplication:
                return LeftOperand * RightOperand;
            case Operation.Division:
                return LeftOperand / RightOperand;
            default:
                throw new InvalidOperationException("Unsupported operation " + Operation);
        }
    }
}

ValueObjectTestFixture provides two ways to exclude those properties from being tested by it. But then you need to write the test cases yourself.

One way is to use one of the ExcludeProperties methods. Typically you call it in the constructor of your test fixture. Below is from CustomText.cs:

    [TestFixture]
    public class CustomTest : ValueObjectTestFixture<CustomTest.CustomObject>
    {
        public CustomTest()
        {
            // Exclude the Name property from being tested by ValueObjectTestFixture.
            ExcludeProperties("Name");
        }
        // ... ...
    }

This completely excludes the property from all the tests administered by ValueObjectTestFixture.

Another less aggressive approach is to override one of the XyzCandidates methods. They are listed below to provide a custom list of properties for the corresponding tests:

Example from CustomText.cs:

        public override IEnumerable<PropertyInfo> EqualsTestCandidates()
        {
            // Exclude the Tag property from equality test.
            return from p in base.EqualsTestCandidates() where p.Name != "Tag" select p;
        }

You opinions is important. Let me know what you think :)

Friday, July 17, 2009

Intercept Explicit Interface Implementation with Inheritance Based Proxy

This is continue from my last post, Intercept Non-Virtual Interface Implementation, Implicit or Explicit.

Krzysztof was absolutely right that it throws MethodAccessException if you just call it. It only works with delegate. But how difficult and/or expensive it is to use delegate?

  1. For each explicit method that we want to intercept, we need to define a new delegate type that matches the method signature
  2. We need to defined a static field of above generated delegate type for each method
  3. Then we use the static delegate instance to make the call to the explicit implementation method in the parent class

This doesn't sound bad to me. There is nearly no runtime CPU overhead, but to hold the generated delegate types, we need some memory. I believe this is well acceptable. After all, we can further optimized it by caching the generated delegate to be reused by the methods with same signature.

I took this as a good opportunity for me to learn the Reflection.Emit API. Thanks to Krzysztof's for the article Working effectively with Reflection.Emit, which led me to the proper tools and approach to start with. Here is what I have achieved.

        public interface IFoo
        {
            void FooMethod(out int i);
            int BarMethod(int i);
        }

        public class Foo : IFoo
        {
            void IFoo.FooMethod(out int i)
            {
                Console.WriteLine("From Foo.FooMethod!");
                i = 100;
            }

            int IFoo.BarMethod(int i)
            {
                return i*i;
            }
        }

        public static void Main(string[] args)
        {
            const string moduleName = "DynamicModule";
            ModuleBuilder mb = EmitUtils.CreateDynamicModule(moduleName);

            Type t = OverrideFoo(mb);

            var proxy = (IFoo) t.GetConstructor(Type.EmptyTypes).Invoke(null);

            int result;
            proxy.FooMethod(out result);
            Console.WriteLine(result);
            Console.WriteLine(proxy.BarMethod(5));
        }

        private static Type OverrideFoo(ModuleBuilder mb)
        {
            TypeBuilder tb = mb.DefineType(
                mb.Assembly.GetName().Name + ".Bar", 
TypeAttributes.Public | TypeAttributes.Class, typeof(Foo), new Type[]{typeof(IFoo)}); var iFooMethods = typeof (IFoo).GetMethods(); var overriders = new List<ExplicitMethodOverrider>(iFooMethods.Length); foreach (MethodInfo iFooMethod in iFooMethods) { overriders.Add(new ExplicitMethodOverrider(mb, tb, iFooMethod)); } Type t = tb.CreateType(); // Initialize static fields for delegates foreach (ExplicitMethodOverrider overrider in overriders) { overrider.InitializeDelegate(t); } return t; }

The output of above program is:

Proxy before call Void DynamicProxy.Program.IFoo.FooMethod(Int32 ByRef)
From Foo.FooMethod!
Proxy after call Void DynamicProxy.Program.IFoo.FooMethod(Int32 ByRef)
100
Proxy before call Int32 DynamicProxy.Program.IFoo.BarMethod(Int32)
Proxy after call Int32 DynamicProxy.Program.IFoo.BarMethod(Int32)
25

The core of this is consisted of two piece of code. One emits the delegate type based on a the MethodInfo of the explicitly implemented base class method. This is done by a static method EmitUtils.GenerateDelegateType, mostly copy from Joel Pobar. Another one emits a static field of delegate type and implement the interface method to call the delegate, which in turn calls the explicit implementation in the base class. This logic is in the the ExplicitMethodOverrider class on which I spent most of my time. The ExplicitMethodOverrider class also provide an initialization method to populate the static field after the type is created.

All the source code can be found here.

Sunday, July 12, 2009

Intercept Non-Virtual Interface Implementation, Implicit or Explicit

Back in April, I blogged about Rhino Mocks' (Castle DP intrinsic) inability to mock non-virtual interface implementation and posted the question in the Rhino Mocks' support group. I didn't receive much feedback until recently, Krzysztof Koźmic killed a good amount of bugs in the DP and so I tried again. What a coincident that Krzysztof also discussed the same issue in his blog 2 days before I sent him the request. :)

Today, the problem is fixed. But Krzysztof also mentioned two limitations. While the 2nd limitation is well understood, I believe there should be a way to overcome the 1st limitation: calling the explicit implementation method in base class.

The problem reminds me of another challenge that I talked about in my post named, C#.Net Calling Grandparent's Virtual Method (base.base in C#). The lesson learned there was that as long as you can get hold of a MethodInfo object, you should be able to emit the call.

I was able to do similar to successfully call the base class explicit implementation method. Code below is to illustration the theory.

    public interface IFoo { void FooMethod(); }

    public class ThirdParty : IFoo
    {
        void IFoo.FooMethod()
        {
            Console.WriteLine("ThirdParty.FooMethod");
        }
    }

    public class Proxy : ThirdParty, IFoo
    {
        private static readonly Action<ThirdParty> baseFooMethod;

        static Proxy()
        {
            var mi = typeof(ThirdParty).GetMethod(
                typeof(IFoo).FullName.Replace('+', '.') + ".FooMethod", 
                BindingFlags.NonPublic | BindingFlags.Instance);
            baseFooMethod = (Action<ThirdParty>) 
                Delegate.CreateDelegate(typeof(Action<ThirdParty>), mi);
        }

        void IFoo.FooMethod()
        {
            Console.WriteLine("Proxy.FooMethod");
            baseFooMethod(this);
        }

        public static void Main(string[] args)
        {
            IFoo foo = new Proxy();
            foo.FooMethod();
        }
    }

I'm not familiar with Emit API enough to write it out so I'll have to leave the rest to DP expert, Krzysztof Koźmic :)

Update 7/17/2009: I was able to implement this, using delegate, with Reflection.Emit. The result was quite good. It is relatively simple, and has minimal runtime CPU performance overhead. See: Intercept Explicit Interface Implementation with Inheritance Based Proxy

Monday, May 18, 2009

Strong Typed, High Performance Reflection with C# Delegate (Part III)

Update: Open source project SharpCut delivers a less than 50K library which does what described in this series plus much more. Check it out.

Content

  1. Inspiration: C#.Net Calling Grandparent's Virtual Method (base.base in C#)
  2. Prototype: Strong Typed, High Performance Reflection with C# Delegate (Part I)
  3. Performance: Strong Typed, High Performance Reflection with C# Delegate (Part II)
  4. Library Usage: Strong Typed, High Performance Reflection with C# Delegate (Part III) <= you are here

In this post, we are going to discuss how you can easily get a Delegate that let you make high performance reflection call by using various extension methods in a library named CommonReflection.

You can download CommonReflection's binary distribution here. Source code can be checked out from Subversion repository  http://kennethxublogsource.googlecode.com/svn/trunk/CommonReflection hosted on Google Code.

There are ten extension methods defined all in one class of the CommonReflection to let you easily obtain a Delegate to any method by name from a type or an instance of object. Amount those, fix (6) extends System.Type and four (4) extends object type. We'll cover all of them in the following sections.

type.GetStaticInvoker<TDelegate>(string staticMethodName)

This extension method finds a static method with the given name regardless of the scope (i.e. it gets private method too) that

  1. The method has the same number of parameters as TDelegate
  2. Each method parameter must be assignable FROM the corresponding parameter of the Delegate at the same position
  3. The method return type must be assignable TO the return type of the Delegate.
  4. For out and ref parameters, they must match exactly.

In a nutshell, you need to make sure you can make the method call with parameters of type of TDelegate and the return result must be of a sub type of TDelegate's return type.

Giving an example, if you have a method and Delegate defined as

        class MyClass {
            private static Sub Foo(Base b, int i, object o) { return null; }
        }

        private delegate Sub ExactFoo(Base b, int i, object o);
        private delegate Base MatchFoo(Sub b, int i, string s);
        private delegate Sub DoNotMatchFoo(Base b, short i, string s);

Both calls below will return a valid Delegate to invoke the method Foo.

            typeof(MyClass).GetStaticInvoker<ExactFoo>("Foo"); // Good
            typeof(MyClass).GetStaticInvoker<MatchFoo>("Foo"); // Good

But this one will get you a null because "short" is not a sub type of "int".

            typeof(MyClass).GetStaticInvoker<DoNotMatchFoo>("Foo"); // Returns null

type.GetInstanceInvoker<TDelegate>(string instanceMethodName)

Similar to the type.GetStaticInvoker, type.GetInstanceInvoker extension method returns a Delegate that can be used to invoke an instance method on a given type. Because the method is obtained from a Type object, it is not associated to a specific instance. Thus, the instance need to be passed as the first parameter to the Delegate when it is called.

The method matching rules are similar to its static brother except that the first parameter of the TDelegate matches the type object and the second parameter of TDelegate matches to the first parameter of method and so on.

  1. The method has the exactly one less parameters than what TDelegate has.
  2. The first parameter of TDelegate must be assignable TO the given type passed to the extension method.
  3. Each method parameter must be assignable FROM the corresponding parameter of the Delegate at the same position plus one (1). i.e. First parameter of the method matches to the second parameter of Delegate and so on.
  4. The method return type must be assignable TO the return type of the Delegate.
  5. For out and ref parameters, they must match exactly.

Given below class and delegate definition.

        class Parent { private Sub Bar(int i, object o) { return null; } }
        class Child : Parent { }

        private delegate Sub ExactBar(Parent instance, int i, object o);
        private delegate Base MatchBar(Child instance, int i, string s);
        private delegate Base DoNotMatchBar(object instance, int i, object s);

Delegate ExactBar and MatchBar are good match for the Bar instance method and DoNotMatchBar won't match because first parameter is not assignable to Parent type.

            typeof(Parent).GetInstanceInvoker<ExactBar>("Bar"); // Good match
            typeof(Parent).GetInstanceInvoker<MatchBar>("Bar"); // Good match
            typeof(Parent).GetInstanceInvoker<DoNotMatchBar>("Bar"); // Returns null

And here is an example of use

            static MatchBar Bar = typeof(Parent).GetInstanceInvoker<MatchBar>("Bar");

            void AnyMember(Child instance) {
                // High performance, type safe call to private method of Parent
                Base b = Bar(instance, 12, "testing");
            }

type.GetNonVirtualInvoker<TDelegate>(string virtualMethodName)

type.GetNonVirtualInvoker works very similar as the type.GetInstanceInvoker extension method. They have exactly the same method matching rules. The only difference is when the method is a virtual method, the Delegate returned by type.GetInstanceInvoker behaves the same as the virtual method itself (i.e. when it is overridden, the overriding method is used), but the Delegate returned by type.GetNonVirtualInvoker always call the method it bound to. A good example is to call the virtual method of grandparent, which inspired the development of CommonReflection.

instance.GetInstanceInvoker<TDelegate>(string instanceMethodName)

While the Delegate returned from type.GetInstanceInvoker can be used to invoke on any instances of the given type, instance.GetInstranceInvoker is bound to the specific instance. Unalike type.GetInstanceInvoker, the parameters of TDelegate for instance.GetInstanceInvoker should match the instance method. There is no special first parameter requirement any more so code reads more natural this way. The method matching rules is same as type.GetStaticInvoker and repeated below.

  1. The method has the same number of parameters as TDelegate
  2. Each method parameter must be assignable FROM the corresponding parameter of the Delegate at the same position.
  3. The method return type must be assignable TO the return type of the Delegate.
  4. For out and ref parameters, they must match exactly.

Taking the "Bar" example again, notice that the first special parameter is removed from "ExactBar" Delegate.

        class MyClass { private Sub Bar(int i, object o) { return null; } }

        private delegate Sub ExactBar(int i, object o);

And a use case.

        class MyClassUser {
            private readonly ExactBar Bar;

            public MyClassUser(MyClass myClass) {
                Bar = myClass.GetInstanceInvoker<ExactBar>("Bar");
            }
            
            void AnyMember() {
                var sub = Bar(12, "object");
            }
        }

CAUTION: Bare in mind that the benefit of high performance is from the reuse of the Delegate. If we had to generate the Delegate again and again for each call, we may end up with more overhead then simple reflection. Obviously, the reusability of instance.GetInstanceInvoker is reduced comparing to type.GetInstanceInvoker because the former strongly bound to one instance while the later can be used for different instances.

instance.GetNonVirtualInvoker<TDelegate>(Type type, string virtualMethodName)

Like instance.GetInstanceInvoker, instance.GetNonVirtualInvoker provides the similar functionality as type.GetNonVirtualInvoker except that it returns a Delegate that is bound to the given instance. It is obvious that the method matching rules are same as instance.GetInstanceInvoker.

Please note that this extension method takes one more argument then others --the argument "type". Unlike instance.GetInstanceInvoker, which can infer the type from the instance, instance.GetNonVirtualInvoker needs to be told about the type to lookup the method. It only make sense that you want to get a non-virtual invoker to a method defined in the ancestor of the given instance. It also implies that the runtime type of the instance must be assignable to the given type.

CAUTION: Same caution about the reusability for instance.GetInstanceInvoker applies.

Get???InvokerOrFail<TDelegate>(...)

By now, we have discussed half of the ten extension methods that we mentioned in the beginning. The other half are just minor variations of what have discussed by suffixing the method name with "OrFail". Below listed all the five get or fail extension methods.

    type.GetInstanceInvokerOrFail<TDelegate>("StaticMethodName");
    type.GetInstanceInvokerOrFail<TDelegate>("InstanceMthodName");
    type.GetNonVirtualInvokerOrFail<TDelegate>("VirtualMethodName");
    instance.GetInstanceInvokerOrFail<TDelegate>("InstanceMethodName");
    instance.GetNonVirtualInvokerOrFail<TDelegate>(type, "VirtualMethodName");

Those get or fail methods differ from their counterpart by throwing an exception when there is no matching method found. Taking the example in type.GetInstanceInvoker, statement below throws NoMatchException instead of returning a null.

      typeof(Parent).GetInstanceInvokerOrFail<DoNotMatchBar>("Bar"); // exception thrown

Properties and Constructors

As of now, properties and constructors are not supported but can be added in future. Stay tuned at CommonReflection. Hey, it is open source, so you can contribute too!

Friday, May 15, 2009

Strong Typed, High Performance Reflection with C# Delegate (Part II)

Update: Open source project SharpCut delivers a less than 50K library which does what described in this series plus much more. Check it out.

Content

  1. Inspiration: C#.Net Calling Grandparent's Virtual Method (base.base in C#)
  2. Prototype: Strong Typed, High Performance Reflection with C# Delegate (Part I)
  3. Performance: Strong Typed, High Performance Reflection with C# Delegate (Part II) <= you are here
  4. Library Usage: Strong Typed, High Performance Reflection with C# Delegate (Part III)

In the Part I, I completed a prototype of extension method that creates a Delegate to make non-virtual invoke of otherwise virtual method. This prototype had since evolved into a extension method library that gets you a Delegate to any method on a given Type object or any object instance. In this post, We'll compare the performance of direct virtual method call, delegate call and reflection invocation using the Invoke method.

Test Setup

The source used for the performance test is Program.cs which forms a simple console application. The performance is measured by calling a virtual method that doesn't nothing but return a literal integer value. The method take two parameters, one reference type and another is value type, and returns a value type. The virtual method then got overridden in the sub class.

        private class Base
        {
            public virtual int PerfTest(int i, object o) { return 0; }
        }

        private class Sub : Base
        {
            public override int PerfTest(int i, object o) { return 1; }
        }

To illustrate how different types of call are made in the test, let's use pseudo code for clarity. Please see the actual source code for the detail.

Direct Virtual Call

Makes the call to a instance of Sub class with a reference type of Base class.

            Base sub = new Sub();
            DateTime start = DateTime.Now;
            for (int i = loop; i > 0; i--) sub.PerfTest(0, o);
Regular Delegate

Create a Delegate from the method Base.PerfTest on an instance of Sub.

            Base sub = new Sub();
            Func<int, object, int> callDelegate = sub.PerfTest;
            DateTime start = DateTime.Now;
            for (int i = loop; i > 0; i--) callDelegate(1, o);
MethodInfo.Invoke

Obtains a MethodInfo object from the Sub type and calls Invoke method on an instance of Sub.

            Base sub = new Sub();
            MethodInfo methodInfo = typeof(Base).GetMethod(methodName);
            DateTime start = DateTime.Now;
            for (int i = loop/1000; i > 0; i--)
                methodInfo.Invoke(sub, new object[] {1, o});
MethodInfo Delegate

Create a Delegate out of a reflected method from Sub type using the extension method in CommonReflection library. Then call the Delegate.

            var callDelegate = new Sub().GetInstanceInvokerOrFail<Func<int, object, int>>(methodName);
            DateTime start = DateTime.Now;
            for (int i = loop; i > 0; i--) callDelegate(1, o);
DynamicMethod.Invoke

Create a DynamicMethod that performs non-virtual invocation to a virtual method on Base type. Then calls the Invoke method on an instance of Sub type.

            Base sub = new Sub();
            DynamicMethod dynamicMethod = Reflections.CreateDynamicMethod(typeof(Base).GetMethod(methodName));
            DateTime start = DateTime.Now;
            for (int i = loop/1000; i > 0; i--)
                dynamicMethod.Invoke(null, new object[] {sub, 1, o});
DynamicMethod Delegate

Create a Delegate our of a DynamicMethod that performs non-virtual invocation to a virtual method on Base type using the extension method in the CommonReflection library. Then call the Delegate on an instance of Sub type.

            var callDelegate = new Sub().GetNonVirtualInvoker<Func<int, object, int>>(typeof(Base), methodName);
            DateTime start = DateTime.Now;
            for (int i = loop; i > 0; i--) callDelegate(1, o);

Performance Test Result

Same test is repeated twice to avoid any warm up effect. And I tested both Debug build and Release build. The result shows nanoseconds per call, which is calculated by calling the method millions of time in a loop to get the total time, then divide the total time by the number of calls to get the per call time.

The Debug build ran on my laptop with Intel Core 2 Due T7300 2GHz and DDR2 5300 RAM yielded this result:

===== First  Round =====
Direct Virtual Call   :      8.281ns
Regular Delegate      :      8.125ns
MethodInfo.Invoke     :  5,468.750ns
MethodInfo Delegate   :      7.969ns
DynamicMethod.Invoke  :  5,468.750ns
DynamicMethod Delegate:     14.844ns
===== Second Round =====
Direct Virtual Call   :      7.969ns
Regular Delegate      :      7.656ns
MethodInfo.Invoke     :  5,468.750ns
MethodInfo Delegate   :      7.813ns
DynamicMethod.Invoke  :  5,468.750ns
DynamicMethod Delegate:     14.844ns

And the Release build test result is

===== First  Round =====
Direct Virtual Call   :      3.594ns
Regular Delegate      :      2.813ns
MethodInfo.Invoke     :  5,468.750ns
MethodInfo Delegate   :      2.813ns
DynamicMethod.Invoke  :  5,625.000ns
DynamicMethod Delegate:      3.750ns
===== Second Round =====
Direct Virtual Call   :      2.813ns
Regular Delegate      :      2.969ns
MethodInfo.Invoke     :  5,312.500ns
MethodInfo Delegate   :      2.656ns
DynamicMethod.Invoke  :  5,625.000ns
DynamicMethod Delegate:      3.594ns

Conclusion

  • The performance of Delegate call is as fast as regular method call. This is quite different from what I learned before in an MSDN article. (Update 5/18: it is confirmed. See on wikipedia and Jon Skeet's blog post
  • The Delegate created from the reflection is as fast as regular method call.
  • The reflection call of MethodInfo.Invoke and DynamicMethod.Invoke is 1500-2000 times slower.

In next post, I'll explain the use of each method in the extension library named "CommonReflection" that you can download its binary here.

Friday, May 08, 2009

C#.Net Calling Grandparent's Virtual Method (base.base in C#)

Update: Open source project SharpCut delivers a less than 50K library which does what described here in one line plus much more. Check it out.

Calling parent's virtual method is easy, you can use base.VirtualMethod(). But C# has no support to call grandparent's virtual method. I guess everybody tried base.base.VirtualMethod() and that won't work.

I have searched the Google for how to call grandparents virtual method in C# learned that this isn't supported by VB.Net and C#. Only C++/CLI gives this power.

I need to do something very similar to the OnMouseDown example in this post. I can code in C++ but this is a class in a big C# project so this is no an option. The IL code in the C++ article reminded me that I should be able to use Reflection Emit to do the same.

    class A { public virtual string foo() { return "A"; } }

    class B : A { public override string foo() { return "B"; } }

    class C : B
    {
        private static readonly DynamicMethod baseBaseFoo;
        static C()
        {
            MethodInfo fooA = typeof(A).GetMethod("foo", BindingFlags.Public | BindingFlags.Instance);

            baseBaseFoo = new DynamicMethod(
                "foo_A",
                typeof(string),
                new Type[] { typeof(A) },
                typeof(A));
            ILGenerator il = baseBaseFoo.GetILGenerator();
            il.Emit(OpCodes.Ldarg, 0);
            il.EmitCall(OpCodes.Call, fooA, null);
            il.Emit(OpCodes.Ret);
        }
        public override string foo() { return (string)baseBaseFoo.Invoke(null, new object[]{this}); }
    }

It works, C.foo() returns "A". But this can obviously be improved in many ways. In next post, we'll try to

  • Create a utility method, or better extension method, that does all the IL generation.
  • Instead of _fooA.Invoke, we can probably use a delegate for type safety and performance.

So that we can write the code like this:

    class C : B
    {
        private static readonly Func<A, string> baseBaseFoo = 
            typeof(A).GetNonVirtualInvoker<Func<A, string>>("foo");
        public override string foo() { return baseBaseFoo(this); }
    }

Looks cool, isn't it?