I am embedding a script engine based on Roslyn into my application and started facing some issues. When loading a reference into my engine, I do the following
var engine = new Roslyn.Scripting.CSharp.ScriptEngine();
engine.AddReference("MyAssemblyLocation");
Questions:
MyAssemblyLocation
assembly is referencing other assemblies, how do I tell Roslyn to load them without doing an engine.AddReference("MyAssemblyLocation");
MyAssemblyLocation
Thank you.
1) Short answer: you need to AddReference on all assemblies whose types are you going to use in the script.
Details: The C# compiler doesn't guess where the dependent files are. An assembly file doesn't specify full paths to all of its dependencies. It only contains their names and that's generally not enough for the compiler to be able to locate the assembly file.
More details: There are two kinds of dependencies. I'll call them compile time dependencies (a) and runtime dependencies (b).
(a) Suppose you have "public class A : B {}" in assembly A.dll, "public class B { }" in assembly B.dll, and your script is using A, say you create a new instance: "new A()". The compiler requires you to add references to both A.dll and B.dll in this case, since A derives from B and the compiler needs to analyze the inheritance hierarchy of each type you use. So B.dll is a compile-time dependency of your script - the compiler needs it in order to analyze your script properly.
(b) Consider another example: "public class A { public object M() { return new B(); } }" in A.dll and the same B.dll as above. Now when compiling "new A().M()" the compiler doesn't need to know about B, since the reference to B only occurs in the body of method M and the compiler doesn't analyze bodies of imported methods. In this case it suffices to add a reference to A.dll in order to compile the script. When the script executes it calls method M. At that point the CLR loads assembly B. This gets a bit complex, so I'll skip details but in common scenarios we'll be able to locate the assembly for you, so you don't need to add the reference explicitly.
2) I'd recommend using the overload of AddReference that takes Assembly object. Something like: engine.AddReference(typeof(SomeTypeInAssemblyFoo).Assembly) to load assembly Foo that contains type SomeTypeInAssemblyFoo.
3) Not a straightforward one. You can enumerate all references using Reflection or Roslyn APIs and load each one of them.
Feel free to ask further questions if the explanation is not clear or you wish to know more details.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With