问题
I have a .net library dll that acts like a functional library. There are a bunch of static types along with static methods.
There is some initialization code that I need to run to set up the library ready for use.
When the assembly gets loaded is there a way to ensure that a particular method is run? Something like AppDomain.AssemblyLoad but called automatically from the assembly itself. I was thinking that maybe there is something like an AssemblyAttribute that could be used?
At the moment I have this initialization code in a static constructor but as this is a library with many entry points there is no guarantee that this particular type will be used.
Thanks!
回答1:
Why do you need all the data to be loaded before any of it is used, rather than just when the first type which needs it is used?
I don't believe there's any way of forcing a method to be run on assembly load, from within the assembly. You could put a static constructor in every type, but frankly I think it just makes more sense to have a single type representing that data and providing access to it - and put a static constructor on that type alone. (If you've got separate bits of data which can be used independently, perhaps create separate types for them.)
回答2:
Yes there is - sort of.
Use the excellent little utility by by Einar Egilsson, InjectModuleInitializer.
Run this executable as a post build step to create a small .cctor function (the module initializer function) that calls a static void function of yours that takes no parameters. It would be nice if compiler gave us the ability to create .cctor(), luckily we rarely need this capability.
This is not a complete DllMain replacement, however. The CLR only calls this .cctor function prior to any methods called in your assembly, not upon assembly load. So, if you need something to happen upon assembly load, you need to have the loading code call a method directly or use the hack I detailed https://stackoverflow.com/a/9745422/240845
回答3:
The following solution is possible only when you have control over the main executing assembly, i.e. it's not suitable for standalone libraries meant for distribution
I've had a similar problem and solved it by creating an assembly-targeted attribute 'InitializeOnLoad' with a Type parameter. Then, in the main executable, I've added a trivial AppDomain.AssemblyLoaded handler, which scans the newly loaded assembly for the aforementioned attribute and calls System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor() on them.
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
public class InitializeOnLoadAttribute : Attribute
{
Type type;
public InitializeOnLoadAttribute(Type type) { this.type = type; }
public Type Type { get { return type; } }
}
// somewhere very early in main exe initialization
AppDomain.CurrentDomain.AssemblyLoad += new AssemblyLoadEventHandler(AssemblyInitializer);
static void AssemblyInitializer(object sender, AssemblyLoadEventArgs args)
{
// force static constructors in types specified by InitializeOnLoad
foreach (InitializeOnLoadAttribute attr in args.LoadedAssembly.GetCustomAttributes(typeof(InitializeOnLoadAttribute), false))
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(attr.Type.TypeHandle);
}
additionaly, if you are afraid that assemblies might have been loade before you hook the AssemblyLoad event, you can simply run through AppDomain.GetAssemblies() and call the 'initializer' for them.
回答4:
It's possible - just add a static constructor to the <Module> class. I don't know how to accomplish this without IL modification though.
来源:https://stackoverflow.com/questions/459560/initialize-library-on-assembly-load