lundi 16 mai 2016

How does lifecycle of class looks like in C#? Is reflection/ reflection only context affect lifecycle?

I had following problem in Java (7): I would like to find all classes that are available in class path that met certain criteria - for sake of simplicity let's assume that class needs to implements some interface. In Java I need to go class by class using reflection, but there are problems with that approach:

  • When I will use reflection to inspect class - it have to be load by class loader, but it might be class that not met my requirements, so it was pointless to load it (class path will be polluted)
  • When class is load by classloader, some code might be executed, like initalization of static fields, code inside static initializers.
  • Class that classloader will load probably have dependencies to other classes - classloader will also load those classes (and execute code, etc.)

I overcome this problem by using Apache BCEL library - it allows you to inspect class on byte code level, so without using reflection. In this case I will use reflection only on class that I'm sure that I want to.

I'd like to have similar logic in C# (4.0). I've found information about App Domains and Reflection only context. General idea is:

  • Create new App Domain
  • Load assembly into new App Domain in reflection only context
  • Examine classes inside
  • Store somewhere names of classes that match my requirements
  • Unload new App Domain
  • Use regular reflection in "Current" App Domain

But I have impression that this approach is good when you are loading/unloading DLLs during application execution (for example if you have plugins support of some sort) and it is too much when assemblies are added to application during compilation time.

So I'd like to gain more knowledge about class lifecycle in c#

There is some class in Assembly. Let’s consider two scenarios:

  1. assembly with class is loaded, but class is never used in application's logic
  2. assembly with class is loaded and class is used in application's logic

(I assume that my application have compile time dependency to some assembly, and application starts - this assembly is loaded already, am I correct?)

My questions are:

  • What is difference in memory between scenario 1 and scenario 2? In Java in scenario 1 class as a part of jar file is in memory, but only in scenario 2 class loader will load actual class.
  • Is there difference in class initialization between scenario 1 and scenario 2? Will be there any code that will be executed in scenario 2 but not in scenario 1? (is there in c# something like static initializers from java?)
  • How about dependencies of this class? If assembly is loaded - all classes and dependencies are fully loaded (scenario 1) or I need to somehow "touch" class to load it?
  • How reflection works from class lifecycle perspective? If I'm inspecting a type (check implemented interfaces, names of methods, etc.), but not create any instance of it with Activator - it is like scenario 1 or scenario 2?
  • Is load assembly in reflection only context make any sense at all in this scenario? I have already this assembly loaded in "regular mode"? Is creation of separate app domain will make any difference here?
  • And finally - if my requirements will change and I would like to inspect classes from assemblies that I can load/unload during execution of my application - does approach with separate app domain is correct now?




Aucun commentaire:

Enregistrer un commentaire