I have complex .NET class library is dependent on several other .NET class libraries, but not all of them are used in every situation. Is there any way to mark them as 'Lazy loading', so I can delete it from folder if I know it is not used at all?
All assemblies are always loaded on demand. If you remove an assembly from a folder, the application will work until the point where it needs to load that assembly.
Related
I have two projects:
ProjectMain (class library)
LibraryProject (class library)
ProjectMain is a class library that should only be compiled as a singular library, no referenced libraries. I require a static class reference from LibraryProject BUT I don't want the LibraryProject assembly to be compiled together with the ProjectMain assembly.
I've tried 'link references' in visual studio but this is no solution as the library assembly is always compiled with the main assembly.
There are clear standard solutions to this issue but I am severely limited by the existing implementation requirements. Only one DLL can be compiled without any of the dependent assemblies being in the execution folder, GAC, private path, reflection etc.
The exact limitations are as follows:
Assembly executed in a sandbox from a third party provider, it only supports adding a single assembly with no direct references/reflection etc (it's horrible but my hands are tied)
We would like to handle the code organisation as best possible which means following standard best practices, unfortunately, due to the above limitation that's proving difficult.
What I would like to know is if there is a way to reference a class within another project without also compiling/using that referenced classes assembly. Possibly a method where the compiler 'embeds' the referenced class at compile time.
If your sandbox does not allow loading other dlls in AppDomain, load it yourself by embedding it. You can use Costura.Fody for this purpose, it is easy to use/install, just reference it from nuget.
Of course, embedding it in every scenario is madness and often comes with completely obscure bugs, which often solvable only by enabling traces in regedit.
So, in your case I would create two projects:
MyDll.csproj //it is my original project, with perfect code design and etc. Lovely.
MyDll.Sandbox.csproj //this one is the same as MyDll.csproj, except it is compiled with additional Costura.Fody reference, into single dll (every reference is put inside)
This way you just need to maintenance that MyDll and MyDll.Sandbox files are the same.
I have multiple DLLs (either managed myself or not managed myself) that I would like to include in a CoreLib.dll so that I do not have to include (possibly) hundreds of DLLs in every application that uses these DLLs. I include the DLLs with a reference directly to the DLL.
So, I would also like to instantiate classes declared within those DLLs in the application I am creating. I cannot do what is pictured in MyApp.exe project, even though I would like to. There is no reference to A, B or C in CoreLib.
How can I accomplish what I want?
EDIT
I used Facade Pattern as suggested, however I am getting a compilation error. Its saying I have to include A.dll in MyApp project. Why? This is what I wanted to avoid. Any way around this?
I do not think this is possible. Adding reference to A, B and C DLLs in CorLib will only mean that CorLib references these DLLs (AssemblyRef metadata table will have one record for each assembly). This does not mean CorLib redefines the assemblies and any types of the referenced assemblies. in MyApp.exe, you would need to reference A, B and C assemblies.
An alternative solution would be to define a Facade class in CorLib and redirect calls to A, B and C DLLs. In MyApp.exe, you will use the Facade class.
You can use ILMerge to merge the assemblies into one.
Then you can use all the classes in that assembly the way you want to.
Here's an example how to merge several assemblies (dlls) into one assembly (dll):
http://www.fishofprey.com/2011/01/ilmerge-to-combine-multiple-dlls.html
Essentaily you just do
ILMerge.exe /out:CoreLib.dll A.dll B.dll C.dll
I think you are confusing DLL (which is in native managed world contain actual implementation) with LIB/OBJ files that contain something that will be merged into EXE/DLL at build time to include implementation into corresponding EXE/DLL.
You have essentially 2 options:
carry all DLLs with your application (normal approach, should be taken unless you have strange requirements). You can either reference assemblies directly from your main application and create classes or make some sort of factory in your CoreLib assembly that will create classes on demand. In later case you may not need to add references to all A..C assemblies (if you not using classes directly, but via some shared interfaces/base classes), but still need to carry them around.
some sort of merging assemblies into one (i.e. ILMerge as suggested by #Alex). This approach would require better understanding of CLR than first one and may not be possible if third party assemblies are involved (due to licensing).
I'm a bit lost with MEF, MAF, Unity ...
This question is about architecture of Winform application.
I've got a main project which contains a Main form and some other forms;
Because i want to include modularity, i'm thinking of using a Plugin System.
What I would like to do is opening each Plugin Dll when the Main Application is opened to reference each with button, toolbar ...
Then i would like to dispose them until they are called.
But i don't want all the plugins to be kept in memory.. just to got a good architecture model.
So first about .NET :
Does dotNet keep only a reference to the dll plugins in memory or all the plugin code ?
I'm thinking of using MEF with LAZY collection of Import, but i need to instantiate them first to get my buttons informations. So second question
If i set the Import Collection to null and lauch the compose() function again, the plugins will be load or wait until call to be load (lazy) ?
Then i would like to dispose them until they are called.
Instead of inspecting imported objects and then throwing them away, you should inspect the import metadata. You can get this metadata by importing Lazy<IFoo,IFooMetadata> or Lazy<IFoo,Dictionary<string,object>>. You can add this metadata to exports with the ExportMetadata attribute.
So first about .NET : Does dotNet keep only a reference to the dll plugins in memory or all the plugin code ?
Once an assembly is loaded it remains in memory, unless you unload the whole AppDomain.
Also, there are no out-of-the-box implementations of ComposablePartCatalog in .NET 4.0 which can be queried without loading the corresponding assembly. But in theory something like that could be done if you store the metadata somewhere outside the assembly. There is a sample of such an implementation in the MEF code on codeplex.
I'm thinking of using MEF with LAZY collection of Import
Using lazy imports will not necessarily prevent assemblies from being loaded. If you have a reference to a Lazy<IFoo> object, then at least the assembly containing IFoo has to be loaded. And as I explained above, the assembly containing the exported IFoo implementation will also have been loaded at that point.
Using Lazy will only postpone the invocation of some constructors, hopefully resulting in faster start-up of your application.
What's the point of dynamically loading an assembly? Isn't it just way simpler to just reference it in your solution/project, saving you all the calls to Assembly.*Load* functions?
Update: Is it useful outside of plugins? What about exclusively in web development, what uses would I find there for dynamically loading an assembly?
Dynamically loading an assembly is useful for anything requiring execution of external code that might not even exist when the hosting program is developed.
For instance, any plug-in system will have to use that feature.
What if you want to make it possible to write plugins for your application, which get loaded at runtime and you don't have that project at compiletime?
You may not have that assembly when you compile your code, think of plugins for instance. You can't compile with a reference to them. Other reason is generating and compiling code and then loadin that Advanced stuff but real use.
GJ
I am running on Windows CE and using the Compact Framework. I need to get a list of all reference assemblies that my application has loaded. It would be nice to be able to get to the AssemblyName (object) of these assemblies.
An example is like getting my running assembly by doing: Assembly.GetExecutingAssembly(); except I need to get the reference to all the other loaded assemblies (3rd party Dlls).
The full framework has the Assembly.GetExecutingAssembly().GetReferencedAssemblies() method but it's not available on the Compact Framework. Any help would be appreciated.
Based on this it would appear that managed dll's are not truly 'loaded' in the sense that they are in the conventional framework. Instead the IL is memory mapped and the JIT just grabs what it needs as it goes along (saving having to maintain a load of memory for code that has executed but is no longer used)
This would explain why the CF provides no way to iterate over the loaded dll's. As to why it doesn't allow iterating over the referenced dlls which are an entirely complie time construct...
As a possible work around:
Use GetExecutingAssembly to get the active code. Ensure that this happens in your executable so it gets the root assembly.
Write some code capable of parsing the dll for the manifest indicating which assemblies are referenced (this need not be managed code - the unmanaged introspection API microsoft provides may even do this for you and the dll format specification is both public and unlikely to radically change in the near future). I suggest black listing dll's loaded from the GAC (though this may be unnecessary).
I guess if there is no API to do this you can try this out ...
Remember, this is not a good way to do this ...
Look for PInvoke calls in Windows CE and call those to figure out what dlls are loaded by the process.
Then iterate through the dlls to check if they have a CLI header. Or you can just try to load the dll as assembly, if it loads then it is a .NET assembly loaded by the application.
I know its not a right way to do this, but this might work.