Loading an assembly / module into a dynamic assembly - c#

I have one assembly that's created already, say Static.dll, and a dynamic assembly I'm creating at runtime, say Dynamic. Dynamic creates some IL code to create a new type from Static.dll. When Dynamic is created (it saves successfully), the executable, when ran, errors out because it's unable to load the assembly Static.dll type. I believe this is happening since the Dynamic exe output can't find this dll (or at least this is my guess).
How can accomplish adding in this Static.dll reference so that when someone runs the resulting executable output of Dynamic that it can find the referenced types?
I know about Assembly.Load(), but this alone doesn't change anything. Or at least, I'm not sure what this gives me since I don't need to use the type at runtime, but rather when running the Dynamic executable.
Lastly, I control the Static.dll, so if there is something I can do with the project to fix it, It could be done, however, it does need to remain separate (I don't want to Emit this library for every time I create a dynamic assembly). Basically, I think I want to have my dynamic assembly to have a .assembly extern mscorlib in it's manifest save Static is place of the mscorlib.
Thanks

How can accomplish adding in this Static.dll reference so that when someone runs the resulting executable output of Dynamic that it can find the referenced types?
The reference will be added automatically. Note that normal assembly-probing rules apply when your dynamic assembly executes, so in order to find the assembly. You must (one of):
ship static.dll alongside dynamic.dll
put static.dll in the GAC (but please: don't do this!)
run dynamic.dll in a custom AppDomain with a custom probing-path configuration that lets static.dll be found
handle AppDomain.AssemblyResolve to provide static.dll
use something like ILMerge to fuse static.dll and dynamic.dll

Related

Refer .NET assembly based on compiler switch

I need to add reference to another assembly in my c# project based on some compiler switch like #ifdirective. For example I want to add reference to logger DLL in my project only when I need it. Is this possible?
As far as I know, a referenced assembly that isn't used AT ALL, isn't a problem. You can even keep it as reference.
As long as your code doesn't trigger the assembly to be loaded, there is no need to have that file available.
I would suggest though to check whether you really need this, and if you can workaround this by creating interfaces and dynamically load the assembly (using Assembly.LoadFrom).

Load an assembly from another location not in the GAC

I have several applications which are required to use the same assembly. This assembly may be changed regularly, and can be installed by different MSIs. For this reason, I do not want to put it in the GAC, it can become a deployment nightmare over time.
If I turn the CopyLocal attribute for this assembly to NO in the application, how do I tell the runtime where to look for the assembly?
E.g. the application is loaded in C:/Program Files/<some directory>/bin
The DLL is in C:/<some other directory>
Is it thus possible to load the assembly in this way?
I've had a look at <codebase>, but I'm not sure the assembly can be strongly signed. And probing seems to work only for the private paths specified as subdirectories of the application?
Please let me know. Thank you.
Use Assembly.LoadFrom to load the assembly into memory, then you can use Activator.CreateInstance to create an instance of your preferred type. You need to user reflection for this:
Assembly assembly = Assembly.LoadFrom("c:\\path\\MyDll.dll");
Type type = assembly.GetType("MyClass");
object instanceOfMyType = Activator.CreateInstance(type);
Take a look on reflection in order to create instances with parameters.
Why do you want to set CopyLocal to "No"? The usual way to avoid "DLL hell" (aka "deployment nightmare") is to ensure that DLL dependencies are copied into the same directory with your program. IMHO, this is the simplest, most straightforward way to guarantee you are loading the DLL you want.
Note also that if you sign the DLL, install it in the GAC, and then in your own program require a specific version (or a minimum version, depending on your needs), that should also address the "DLL hell" scenarios. I.e. the presence of other versions of the DLL won't conflict, because you've required a specific version and .NET can reliably distinguish the correct version from an incorrect one.
Barring those approaches...
It's not clear what your exact requirements are. However, if you are trying to provide a way to identify an assembly that's not in the usual assembly-loading paths, there are at least a couple of mechanisms you can use.
One way is to use ApplicationBase and PrivateBinPath to control how .NET searches for your assemblies.
Another way is to handle the System.AppDomain.AssemblyResolve event.
That event will be raised any time .NET tries to load a referenced assembly and can't find it. Your handler can then perform whatever search it needs to (or just use a fixed path for that matter), load the assembly itself (e.g. using Assembly.LoadFrom()), and then return that via the event's arguments object.
Note that the AssemblyResolve event is only raised if .NET can't find a DLL to load. So that would not be an appropriate solution if it's not tolerable to have a different instance of the DLL that satisfies the reference requirements for the program of that DLL.

C# Load in a DLL at runtime, second load does not work

I am generating C# code and compiling it to a DLL at runtime, and then loading the DLL into the program and calling its methods.
But when I compile the DLL again and try to load it in, .NET already thinks it has the DLL loaded and so does not re-load the DLL. I can tell this is the case as any methods I call still act in the same way even though I changed their code. Also on restarting my program the methods start working as expected.
I understand that at this point the usual advice is to use a second AppDomain and add MarshalByRef to all my classes, but this approach is not working for me; inside the DLL I need to cast incoming data which doesn't work when using remoting as the object is a __TransparentProxy and casting it to what I need returns null.
So my other option as far as I can see is to trick .NET into thinking it's loading a different DLL/type into the program so it actually loads it.
So far I have tried:
Each time I compile the code into the DLL, the DLL is output to a different folder from before.
Adding a GUID to the type I am trying to load so the type always has a different name
Changing the GUID in the AssemblyInfo.cs file
...but still the new DLL is not loaded in. Even changing the output folder, looking at the property `assembly.Location' shows the old DLL path. so what is still making it think it is the same?
How I load the DLL at runtime:
Assembly assembly = Assembly.LoadFrom(dllFilePath);
Type type = assembly.GetTypes().Single(t => t.BaseType.Name == "Parser");
var classInstance = Activator.CreateInstance(type);
return classInstance as Parser;
The Assembly.LoadFrom method will load new assembly if it has a different identity. Give a unique name to the newly generated assembly (not only the file name).
http://msdn.microsoft.com/library/1009fa28(v=vs.110).aspx

Assembly.GetType() fails to load List`1[[MyModel]] type from ReSharper Plugin only

I have a R# plugin and a test project (not a R# test project, but a simple, plain unit-test project). In the code of the plugin I do some type resolution from serialized type information. On such type is a list of object from one of my model classes. The serialization of the type looks like this:
"System.Collections.Generic.List`1[[Model.Foo, Model]], mscorlib"
I load this type (or, actually, Json.NET does) with the following calls:
Assembly assembly = Assembly.LoadWithPartialName(assemblyName);
Type type = assembly.GetType(typeName);
In my test project, when I run this code, everything works just fine. The assemblyName is "mscorlib" and the first line resolves the mscorlib assembly (as an instance of RuntimeAssembly). The typeName is "System.Collections.Generic.List`1[[Model.Foo, Model]]" and the call to GetType() resolves my type.
When I run the R# plugin, however, the GetType() call returns null. Till that line everything looks like when I execute from the test project. Both projects reference the "Model" assembly. When I try to resolve only the type "Model.Foo, Model" using the exact same mechanism, it works in the R# plugin and the test project both.
When I allow the GetType() call to throw exception, the FileNotFound exception (of course only thrown when running the R# plugin) tells me that the "Model" assembly cannot be found. The stacktrace contains a list of locations that were scannened. All these locations are below the VisualStudio installation directory.
As mentioned, the two lines above are actually part of Json.NET. Therefore, I cannot change them. However, I completely eliminated Json.NET while narrowing down this problem. Just the two lines above, with the respective string values of assemblyName and typeName suffice to reproduce the problem.
Can anybody tell me where this different behavior originates from? Or better: tell me how to solve this problem?
Thanks in advance!
Best,
Sven
When .net is searching for your Model assembly, it only looks in the search paths set up by the application, i.e. the VS install dir and so on. It doesn't search in the location of your plugin. You would probably need to add an event handler to AppDomain.CurrentDomain.AssemblyResolve. Check for who's calling, and what assembly they're after, and you can either load the assembly, or find it in memory and return it. It's generally better to return an assembly that you have in memory than to try and load it again (due to load contexts). You can use the AssemblyResolver class to make it easy to install and uninstall a handler to load the assemblies for you.
Also, based on the fact this is called "Model", if this is for saving/loading settings, you'd be better off using ReSharper's settings infrastructure, which provides a lot of flexibility, and removes the need for the AssemblyResolver.

Add class into current assembly

I have a current assembly in my application and I would like to add a class from external cs file into this assembly. Is it possible to do it? I would like to use it like plug-ins. Now I'm trying use:
System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly();
and Activator,but without success. My application is using Roslyn, so maybe it can do it.
Any idea will be appreciated.
Edit: Next problem with it is: Can I use external file (cs file with class) to get instance from this file but the constructor of class needs reference to sceneManager from current assembley. So is possible to send a reference to Roslyn of something like that and get instance of class from it?
You cannot modify an existing assembly that has already been loaded.
Instead, you can compile code to a new assembly (using Roslyn, CodeDOM, Sigil, or similar libraries) and load that assembly using reflection.
A '.cs' file by itself is just text. You can't do anything with it without compiling it through some route. But no: you can't add extra classes into an assembly at runtime. You can compile the code at runtime via CSharpCodeProvider or similar, and load the generated assembly. It is a lot of messing, though. Depending on the context, tools like Iron Python may be preferable, if you need to do a lot of things from scripts at runtime.

Categories