Outshined said:
As I mentioned, I am building a class library, contained within its own
assembly. If possible, I want to have my library be independent and not
force people to explicitly initialize it before using classes from it. Ergo
my interest in executing initialization when this class library assembly is
loaded. But in order to handle the AppDomain AssemblyLoad event, I must
first register the handler somehow, using the following line:
AppDomain.AssemblyLoad += new
AssemblyLoadEventHandler(MyAssemblyLoadEventHandler);
Can this registration occur inside the class library assembly, or must it be
outside - somewhere in the calling application.
I believe it must be outside.
Is there a single class which is always going to be used before the
registration is needed? If there is, you could put a call in its static
initializer to do the registration.
I wouldn't mind having that sample code! (e-mail address removed)
Unfortunately the sample won't handle the above. I don't know of
anything which you can put in an assembly to say, "When this assembly
is loaded, call <x>."
Here it is though, for better or worse. Note that in real code you
would of course handle exceptions, use namespaces, etc.
Driver.cs:
using System;
using System.Reflection;
using System.Threading;
public class Driver
{
static void Main()
{
// Make sure we load the assembly containing the custom
attribute
// first! (Loading another assembly within the
AssemblyLoadEvent is
// probably not a good idea.)
Type t = typeof(InitializeOnLoadAttribute);
// Now add the handler
Thread.GetDomain().AssemblyLoad+=new AssemblyLoadEventHandler
(InitializeTypesOnLoad);
Assembly.LoadFrom ("library.dll");
}
static void InitializeTypesOnLoad(object sender,
AssemblyLoadEventArgs args)
{
Assembly loaded = args.LoadedAssembly;
foreach (Type type in loaded.GetTypes())
{
if (type.IsDefined(typeof(InitializeOnLoadAttribute),
false))
{
ConstructorInfo initializer = type.TypeInitializer;
if (initializer!=null)
initializer.Invoke(null, null);
}
}
}
}
Common.cs:
using System;
[AttributeUsage(AttributeTargets.Class)]
public class InitializeOnLoadAttribute : Attribute
{
}
Library.cs:
public class ClassNeedingRegistration
{
// Note - this must *not* have =false at the end,
// otherwise it will be set to false every time the type
// initializer is run, before the test for it being false.
// We want the default value (false), but only the first time...
static bool initialized;
static ClassNeedingRegistration()
{
if (!initialized)
{
initialized=true;
Console.WriteLine ("Registering class.");
}
}
}
public class ClassNotNeedingRegistration
{
static ClassNotNeedingRegistration()
{
Console.WriteLine (
"This class does not need to be registered.");
}
}
Compiling:
csc /target:library /out:common.dll Common.cs
csc /target:library /out:library.dll /r:common.dll Library.cs
csc /r:common.dll Driver.cs
Running:
Driver.exe produces output of:
Registering class.
(It only prints it once, even if you call the type initializer multiple
times. It could well be that some of your classes won't need the kind
of guard I've put around it to make sure it only effectively gets
executed once, but I thought I'd show you the pattern anyway.)