Last active
December 2, 2021 09:59
-
-
Save rubensteins/0f1cdace9207effb5ec28787644bb38e to your computer and use it in GitHub Desktop.
Tests performance of Reflection
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections; | |
using System.Collections.Specialized; | |
using System.Globalization; | |
using System.ComponentModel; | |
using System.Reflection; | |
using System.Diagnostics; | |
namespace ConsoleApplication1 | |
{ | |
class Program | |
{ | |
delegate void MethodToEvaluate(object[] parameters); | |
static void Main(string[] args) | |
{ | |
long times = 1000000; | |
// creates the parameter needed for the tests | |
IDictionary paramAndValues = new OrderedDictionary(); | |
paramAndValues.Add("id", "1"); | |
paramAndValues.Add("name", "product name"); | |
paramAndValues.Add("description", "product description"); | |
paramAndValues.Add("price", "100"); | |
object[] parameters = new object[]{ new Product(), paramAndValues }; | |
// launch the test cases | |
EvaluateMethod("Constructor", ConstructorTest, null, times); | |
EvaluateMethod("Constructor using reflection", ConstructorTestReflection, null, times); | |
EvaluateMethod("Method call", MethodCall, null, times); | |
EvaluateMethod("Method call using reflection", MethodCallReflection, null, times); | |
EvaluateMethod("Setting properties", SetProperties, parameters, times); | |
EvaluateMethod("Setting properties using reflection", SetPropertiesReflection, parameters, times); | |
Console.ReadLine(); | |
} | |
// evaluates a method the specified number of times and print performance information | |
static void EvaluateMethod(string testName, MethodToEvaluate method, object[] parameters, long times) | |
{ | |
Console.WriteLine(testName); | |
Stopwatch timer = new Stopwatch(); | |
timer.Start(); | |
for (long i = 0; i < times; i++) { | |
method(parameters); | |
} | |
timer.Stop(); | |
Console.WriteLine($"Time elapsed (ms): {timer.ElapsedMilliseconds} which is {timer.ElapsedTicks} ticks for {times} calls.\n"); | |
} | |
static void ConstructorTest(object[] parameters) | |
{ | |
Product prod = new Product(); | |
} | |
static void ConstructorTestReflection(object[] parameters) | |
{ | |
Activator.CreateInstance(typeof(Product)); | |
} | |
static void MethodCall(object[] parameters) | |
{ | |
Product.TestMethod(0, "test"); | |
} | |
static void MethodCallReflection(object[] parameters) | |
{ | |
MethodInfo method = typeof(Product).GetMethod("TestMethod", BindingFlags.Public | BindingFlags.Static); | |
object[] paramValues = new object[]{ 0, "test" }; | |
method.Invoke(null, paramValues); | |
} | |
static void SetProperties(object[] parameters) | |
{ | |
Product prod = (Product)parameters[0]; | |
IDictionary values = (IDictionary)parameters[1]; | |
prod.Id = Convert.ToInt32(values["id"]); | |
prod.Name = (string)values["name"]; | |
prod.Description = (string)values["description"]; | |
prod.Price = Convert.ToDecimal(values["price"]); | |
} | |
static void SetPropertiesReflection(object[] parameters) | |
{ | |
Product prod = (Product)parameters[0]; | |
IDictionary values = (IDictionary)parameters[1]; | |
SetProperty(prod, "Id", values["Id"]); | |
SetProperty(prod, "Name", values["name"]); | |
SetProperty(prod, "Description", values["description"]); | |
SetProperty(prod, "Price", values["price"]); | |
} | |
#region Helper Methods | |
static void SetProperty(object obj, string name, object value) | |
{ | |
// searchs for the property | |
PropertyInfo prop = typeof(Product).GetProperty(name); | |
// try to convert a string value to an object (using the type converter) | |
object propertyValue = BuildObjectValue(value, prop.PropertyType); | |
// sets the property value | |
prop.SetValue(obj, propertyValue, null); | |
} | |
static object BuildObjectValue(object value, Type destinationType) | |
{ | |
// if we have a value that needs conversion | |
if ((value != null) && !destinationType.IsInstanceOfType(value)) { | |
Type targetType = destinationType; | |
// if the value is a string, try to convert it to the target type | |
if (value is string) { | |
value = ConvertStringToType((string)value, targetType); | |
} | |
} | |
return value; | |
} | |
static object ConvertStringToType(string value, Type destinationType) | |
{ | |
object result = null; | |
// try to get a type converter | |
TypeConverter converter = TypeDescriptor.GetConverter(destinationType); | |
if (converter == null) { | |
return value; | |
} | |
// try to convert the string using the type converter | |
result = converter.ConvertFromString(null, CultureInfo.CurrentCulture, value); | |
return result; | |
} | |
#endregion | |
} | |
class Product | |
{ | |
public int Id { get; set; } | |
public string? Name { get; set; } | |
public string? Description { get; set; } | |
public decimal Price { get; set; } | |
public static void TestMethod(int id, string value) | |
{ | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This code was converted from a snippet from 2006 (https://web.archive.org/web/20201019153235/http://www.manuelabadia.com/blog/PermaLink,guid,772c7152-b00e-4334-b677-bfbdcd8e6b5d.aspx). I added a Product-class and removed references to ProductDal (instead gave Product a static method to call). The code compiles and runs fine with dot net 6, but gives a few null-related warnings.