views:

703

answers:

6

Is it possible to run some code when an assembly is loaded, without doing anything specific in the loading code? What I am looking for is like a static constructor on a type.

Eg:

Assembly A does not know about Assembly B, but B does know about A. Assembly A needs to know certain things about B if B is loaded. When Assembly B is loaded by the runtime (referenced, or explicit), I want a piece of code (static method or attribute) to be executed that calls a method in Assembly A.

The root cause of this problem is unknown types being encountered when serializing a type in A that contains types from B not known at compile time as interfaces are used.

+3  A: 

(edit - applies to C#; for a C++ approach, see this answer)

Basically, no: you can't. This would be a huge attack surface, and isn't allowed. You might want to put a static ctor on some of the B types that ensure the init code is executed, but that is about it...

Marc Gravell
Why is it an attack surface?
Robert Wagner
It seems that it would be fairly easy to hide code in there that no code knowingly invokes - hard to trace, etc. Let alone the question of which thread should run it... Maybe I can't vocalize it properly, but it sounds unwise to me. But it is moot since you can't do it anyway ;-p
Marc Gravell
That's it - i'm a sad panda now. Oh well... Thanks anyway.
Arnis L.
+2  A: 

You should probably revisit your serialization approach to mitigate this problem. If you serialize using ISerializable and the SerializableAttribute attribute, you can make it such that the serialization graph will load assembly B when necessary without assembly A ever having to explicitly know about assembly B.

Jeff Yates
How can I identify and load Assembly B using this method?
Robert Wagner
If you serialize using, say a BinaryFormatter, any types in your serialization graph that implement ISerializable will have their constructors called during the deserialize, in which you can call whatever code you need.As, when you serialize, the serialization queries for the interface...
Jeff Yates
... it doesn't matter if A only refers to B's types by an interface, they will serialize properly.
Jeff Yates
We are using XML Serialization with WCF.
Robert Wagner
Then you may well be clean out of luck with this approach. There is a SoapFormatter that persists ISerializable types to SOAP XML and there are XmlFormatter's available online (though I don't know how successful they are).
Jeff Yates
+10  A: 

The CLR supports module initializers. You'd have to hack C++/CLI code or ilasm.exe to use them.

Hans Passant
Interesting; didn't know about them...
Marc Gravell
+1 for this....
Preet Sangha
+2  A: 

You can use static constructors in .Net, but unfortunately they don't do what you want. Static constructors are only executed just before a type is used. See http://msdn.microsoft.com/en-us/library/k9x6w0hc(VS.80).aspx for details.

You might get some mileage from subscribing to your AppDomain's AssemblyLoad event. See http://msdn.microsoft.com/en-us/library/system.appdomain.assemblyload.aspx.

In your event handler you could reflect on the newly loaded assembly, and get it to execute whatever code you like.

Antony Perkov
Unfortuantly since only one out of the 30 odd assemblies needs this registering done, AssemblyLoad may be a bit over overkill.
Robert Wagner
A: 

Using a mixed assembly you can get DllMain to run on an assembly load.

Mike
A: 

This is not a direct answer to your question, but those interested in running code after loading a test assembly might want to have a look at:

NUnit: SetUpFixtureAttribute

MSTest: AssemblyInitializeAttribute

Marco