Thursday, January 18, 2024

THE CASE OF THE MYSTERIOUS CLASS LIBRARY

The Investigation

I just found a dusty, purple flash drive behind my desk. It doesn't look familiar. I wipe it clean, pop it into the PC, and run a virus check. Clean. When we open it we see a number of files, all DLL class libraries. The first one is "Zodiac.dll" Whoa, like the Zodiac Killer? We need to investigate. It is at moments like this that .NET Reflection comes to mind.

.NET Reflection allows us to inspect class libraries and discover types, methods, and properties at runtime. Furthermore, we can instantiate the types, call the methods, and change the properties.

First, we want to reveal what types it contains. We create a new .NET Core 8 console application and then copy the Zodiac.dll to the project folder. Let's load it:

using System.Reflection;

var DLL = Assembly.LoadFile(@"<AbsolutePath>\Zodiac.dll");

We want to list the types, if they are public, and what the base type is:

foreach (Type type in DLL.GetTypes())
{
    Console.WriteLine(type.Name + " (" + (type.IsPublic ? "public" : "not public") + 
                        "), Base Type: " + type.BaseType);
}

The Discovery



Aha! Chinese Zodiac. How are these types connected? Looking at the base types, we can see that CancerZodiacModel inherits from ZodiacModel, which in return inherits from  BaseZodiacModel.

Next, let's get the methods for the Chinese Zodiac class, the parameters, and the return types:

Type type = DLL.GetType("Horoscope.ChineseZodiac");  
foreach (MethodInfo info in type.GetMethods())
{
    var paramInfo = "";
    foreach (var param in info.GetParameters())
    {
        paramInfo += param.ParameterType.Name + " " + param.Name;
    }
    Console.WriteLine(info.Name + " " + paramInfo);
}

Just one method: GetZodiacSignForDate, one parameter: requestedDateTime, and a return type of ChineseZodiacModel.

The Arresting Conclusion

Of course we could have just referenced this DLL in Visual Studio to discover it's public types, methods, and properties. The power of Reflection lies in the fact we can do this analysis at runtime and dig deeper to show private types, methods, and properties. This allows us to easily write a bit of code to examine all the DLLs in a folder and produce a report.

Now let's invoke the method and see what we get:

Type type = DLL.GetType("Horoscope.ChineseZodiac");
var method = type.GetMethod("GetZodiacSignForDate");
DateTime date = DateTime.Parse("1/18/24");
dynamic result = method.Invoke(type, new object[] { date });
var englishName = result.ZodiacEnglishTranslation;
var personality = result.ZodiacPersonality;
Console.WriteLine(date.ToShortDateString() + ": " + englishName + ", " + personality);


Note the use of the dynamic type of the result. The result is of type "ChineseZodiacModel" but as we haven't referenced the DLL, we can't use the type in the declaration. Dynamic let's us use the properties "ZodiacEnglishTranslation" and "ZodiacPersonality" without getting a runtime error.

So much for a quick taste of Reflection in .NET.

To learn more, follow these links:

No comments:

Post a Comment

THE CASE OF INHERITANCE IN ENTITY FRAMEWORK CORE

The Investigation Entity Framework Core simplifies working with databases for .NET developers. Instead of creating tables and stored procedu...