Choosing what architecture NuGet.Protocol Downloads
Hi there!
I'm working on a sort of addon-like system for one of my project, and would like to handle addon's dependencies using NuGet repositories. Right now, I'm downloading the DLLs requested by an addon (for instance in my test, it was
SpacedGrid-Avalonia
version 11.0.0
) into a folder, then loading the DLLs using Assembly#Load
.
However, when calling this method, I'm getting a Bad IL Format
, which I guess means the downloaded DLLs was not for the right machine arch. Here's my code for downloading from NuGet repos:
75 Replies
what exactly do you do with the file that you write?
I load it using
Assembly.Load
yes, that will not work
a nupkg isn't an assembly
I also tried
LoadFromFile
, but it stills throw me the "Bad IL"it's a zip file
well the file the code downloads is a dll
oh I think I get what you mean
Ohh okay I am very stupid
i can assure you
CopyNupkgToStreamAsync
does not download a DLL. i mean, it says in the name, it downloads a nupkg
if you open that file in a program like 7-zip you will see it has some directories and a bunch of files in ityup sorry, I convinced myself it was a dll after looking at the downlaoded file 😭
one (or even more) of those files is a DLL
it is somewhat difficult to select the right DLL from the nupkg
So once downloaded, I have to unpack the Nupkg file right?
ah, because of the different frameworks?
yes, mainly
i am pretty sure there are APIs in the nuget client to select the right DLL, though i don't know what they are
Gotcha, I'll dig into this more now I'm getting the error 😂
Thanks for the help :Lovely:
i think https://github.com/waf/CSharpRepl/blob/main/CSharpRepl.Services/Nuget/NugetPackageInstaller.cs is a good example of what needs to be done, the code is kinda complicated, but you can see what it does starting from "InstallAsync"
the implementation of
GetRuntimeGraph
is kinda shitty, i would not have done it that way, it might not work for you. otherwise, the code is pretty easily adapted to whatever you needOki! I got it working, loading the DLL is no longer a problem
However, I am doing the "same thing" (I mean loading a dll, and this time I'm sure it's one lmao) for my addon system, however even if I load the dependency before the addon's dll, it cannot found the dependency's DLL
Tried with the exact same version as well (of the dependency I mean) and nope, I'm getting the whole
System.IO.FileNotFoundException: Could not load file or assembly 'SpacedGridControl.Avalonia, Version=11.0.0.2, Culture=neutral, PublicKeyToken=null'. Le fichier spécifié est introuvable.
what are you passing to Assembly.Load
to be clear, it does not take a file path
for loading the dep or addon?
yea I'm passing a stream iirc
That's for the dependency (using LoadFile instead to see if it changed anything but nope)
and yea for addon I'm just passing a stream
Assembly.Load(await File.ReadAllBytesAsync(addonDllFile))
you will have to explain more about this plugin system
are you using AssemblyLoadContext?
not at all
should I? x)
yes, probably
there is an article about it here https://learn.microsoft.com/en-us/dotnet/core/tutorials/creating-app-with-plugin-support
Create a .NET Core application with plugins - .NET
Learn how to create a .NET Core application that supports plugins.
AssemblyLoadContext allows the plugins to not conflict with each other
owh sweet
thanks 👍
and, i am not really sure what you need this nuget thing for--if it's just because your pluigin depends on this library, i think the article proposes a much easier way to do it
well it's to let addons use dependecies that are not in my program
and as dlls cannot be "combined" I though it was the only way
they cannot be combined, the way the article proposes is to use a folder instead
the folder contains the plugin and all of the DLLs it uses
and there is a
.deps.json
file which will tell the plugin loader exactly what is whatso if people (normal users I mean) wanna add a plugin, they'll have to put a whole folder?
well a zip technically
in case the plugin has dependencies, yes, downloading a zip and extracting it as a folder somewhere would be the way to do it
i think it is going to be much easier and less problematic than trying to implement some kind of dependency loader yourself
Hum well actually I'll end up with the same problem
cuz at the end in both situation I have DLLs to load (dependencies I mean)
yes, but, the API handles it for you
https://learn.microsoft.com/en-us/dotnet/core/tutorials/creating-app-with-plugin-support#load-plugins
the
AssemblyDependencyResolver
thing finds the dependency DLLs which are next to the pluginOhh
so, when the plugin tries to find
SpacedGridControl.Avalonia
(for example), it calls into the PluginLoadContext
object you made for that plugin
it calls your override of Load
, and you can do any logic you want in thereOki, I reworked my logic behind, but I still have the same error
Now both the addon & dep are in the same folder
Here's how I gather the addon's dll files
And for each, I'm loading it this way:
I'm not sure if I did something wrong this time x)
you need to build the addon so that it copies its dependencies and generates the dependency file
so, in your
SdkEditorTestAddon.dll
, you need to add this to your csproj:
then, try building it again, and look at the build output
(it might not be fully right, so, can you send a picture of it)well the problem is that he also generates dll for libs that are already in my app
ok, so,
you have
<ProjectReference Include="MyApp.csproj" />
somewhere in ther
change it to <ProjectReference Include="MyApp.csproj" Private="false" ExcludeAssets="runtime" />
this will tell your plugin to not depend on any of the app's libaries even though you have referenced ityou'll beat me, but I was referencing each deps ;-;
what do you mean
no, it's OK that you use the libraries in the plugin
it just will not copy them to the build output
sorry i was not clear
I got this for all other libs, referencing their DLLs
oh
is there a reason you are not doing
ProjectReference
insteadBecause I am stupid :blobsweat:
Although it's been a solid time I code with C#, its whole env is a bit new to me
while I'm used to Gradle with Java, so it's even harder to move on
Okay, using the project reference i'm getting some unresolved deps from the addon
uh, would you mind showing the csproj file you have for the main program
yessir
Thanks for the time you're taking to help be btw :love:
if you try doing
dotnet build
on the plugin does it have the same errorshuh, nope, all I get is warnings
but I think it got built correctly
maybe try restarting rider
WHAT all the errors from Rider disapeared 🤣
it is probably just a little bit confused
ahh the csproj got restored, it's maybe beacsue of that?
the app's one I mean
yeah that is probably what happened
ahh sorry, didn't think about it :blobsweat:
ok, anyway, when you look at the build output for the plugin, what does it look like
I'm getting all of this
hm. this is a somewhat unpleasant situation
Oh :pandaSob:
does adding
<PackageReference Include="Avalonia" Version="11.0.0" ExcludeAssets="runtime" />
remove all of the avalonia DLLsyup, got a lot less
you will have to add to your project file to remove all of the avalonia DLLs that shouldn't be there
unfortunately i don't think there is a good way to do it automatically
Got it
In my case rn I'm using local things, but I plan to put my project on nuget for easier use
will those still be required?
yup that worked btw
Thanks again!
i do not think it is needed--i think the DLLs will just be ignored if they are there
the problem is that, when you reference SpacedGridControl.Avalonia, it thinks you also need all of Avalonia
but you do not, because it comes with the plugin host
so, it will copy the DLLs. they will be ignored, because it will always choose the DLLs from the plugin host anyway. so, it doesn't cause any harm. but it is kind of unclean. and writing ExcludeAssets is the only way to fix it currentlly
ohh oki I see
sort of conflicts from two sources
yes
anyway, now you can copy that build output folder to the folder for the plugin
and it should just work
Yup it worked like a charm! Thanks you very much 👍
welp, me again, I think I'm too much used to Java's generic types, but I am getting something wrong here? :thonk:
yes, it is not possible
even if you declared
ISettingType<out T>
using out
because bool
is a value type, variance conversions do not workThere's nothing similar to
?
for generic types in C#?no, there are no wildcards
hum got it, thanks 👍
I think i'll just use object in this case
i mean without any generic type xD