背景:
阅读新闻

Testing a Cloned Object Using Reflection

[日期:2003-10-06] 来源:DotNetJunkies  作者:Ben Hinton [字体: ]
Testing a Cloned Object Using Reflection  

By Ben Hinton
Published Date:
8/20/2003
Tested With:
ASP.NET v1
Check or Rate Page:
No VB.NET Download Download C# Code Rate This Article

Testing a Cloned Object Using Reflection

The Problem with Cloning

The .NET Framework provides the IClone interface so that you can implement your own Clone() method in your class. However, since IClone is just an interface it is up to you to make sure that you are copying the properties/methods etc to the new object correctly. This can present a problem when testing your code as you need a way to programmatically check that it has all the same properties and methods, both public or private, that you would expect. In order to make sure of this you need to be able to compare the old and new objects and the System.Refelction namespace enables you to do just this.

Using Reflection

Reflection in .NET enables you to interrogate an assembly/object at runtime and see what's inside. You can do lots of things with reflection such as listing the properties/methods and invoking methods.

I will assume that you have already cloned your object in some way, either by serializing your object, creating a new one and de-serializing the original into the new or perhaps by some other more manual way. In either case, the following code should work.

Firstly, make sure you add the System.Reflection namespace :

using System;
using System.Reflection;

Next, we need to test the original object to check that it actually has a Clone() method which you can do like this :

// Is there a Clone method present?
MethodInfo info = originalObj.GetType().GetMethod("Clone");

Now we need to invoke the Clone() method to produce a new object :

object clonedObject = originalObj.GetType().InvokeMember("Clone", BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod ,null , originalObj, null);

So we now have two objects which we can compare them. This is how we can do it :

private static bool CompareCloneToOriginal(object original, object cloned) {
  bool matchMethods = false;
  bool matchFields = false;

  // Compare Methods (public and private)
  MethodInfo[] originalMethods = original.GetType().GetMethods(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
  MethodInfo[] clonedMethods = cloned.GetType().GetMethods(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);

  if (clonedMethods.Length == originalMethods.Length) {
    matchMethods = true;
  }

  // Compare fields (public and private)
  FieldInfo[] originalFields = original.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
  FieldInfo[] clonedFields = cloned.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);

  if (clonedFields.Length == originalFields.Length) {
    matchFields = true;
  }

  if (matchFields != matchMethods)
    return false;

  return true;
}

You will notice the use of the BindingFlags enum in the above code. These don't have to be in any particular order but there are more that you can choose depending on what kind of methods/properties etc you want the reflection classes to get. The comparison we are doing is of course fairly simple. You could alter the code without too much fuss to be able to systematically invoke each method and property to see if they are returning the right results and are behaving in the expected manner. However, I will leave that for you to implement.

The full source code to a static helper class with the above code is downloadable on this page.

收藏 推荐 打印 | 录入:木鸟 | 阅读:
相关新闻      
本文评论   [发表评论]   全部评论 (0)
热门评论