I have an abstract class that will need to be able to load files contained in the assembly that made an object of the class. What I could use is FileAssembly = Assembly.GetCallingAssembly()
for every child of my class, but since it is a library that people can extend I want that to happen without requiring them to do this.
My setup right now is something along the lines of:
public abstract class ExternalResource : Resource, IDisposable
{
public string File { get; private set; }
protected Assembly FileAssembly { get; set; }
protected ExternalResource(string id, string file)
: base(id)
{
File = file;
}
//and s'more code
}
public class Sound : ExternalResource
{
public Sound (string id, string file)
: base(id, file)
{
//this is the line I want to be able to get rid of
FileAssembly = Assembly.GetCallingAssembly();
}
}
Someone using my library could make their own ExternalResource without setting the FileAssembly, which is not desirable. It gets really messy if they would inherit from a class that already inherits from ExternalResource. How can I get the assembly of the code instantiating the object? Any other way to work around it without too much changing to the existing system would be appreciated too!
You can use the StackTrace class from the System.Diagnostics namespace:
In the constructor of your ExternalResource class:
var stack = new StackTrace(true);
var thisFrame = stack.GetFrame(0); // ExternalResource constructor
var parentFrame = stack.GetFrame(1); // Sound constructor
var grandparentFrame = stack.GetFrame(2); // This is the one!
var invokingMethod = grandparentFrame.GetMethod();
var callingAssembly = invokingMethod.Module.Assembly;
The references to thisFrame and parentFrame are there simply to aid understanding. I would suggest that you actually walk up the stack frame and do it more robustly, rather than just assuming that it's always frame 2 that you want (which won't give the right answer if you have an additional subclass).