Conversation
|
@NPatch Sorry for the late reply, other more important things came up. I looked at your patch, and I still have a few things that bother me. Implementing your own deserializer is something that has also crossed my mind. However, by disabling the The funny thing is though, that when I use my original version and run the You also mention that the
I really appreciate your suggestions, but so far I am not very happy with the proposed solution.. |
|
For what it's worth, I managed to compile everything and make it run, again by reconnecting the csproj of the NpmRegistry.Wrapper, setting it to .NET10, but keeping the dependencies on .NET9..........I have no clue why or how, but it does work with the rest as-is, as in using the JsonSerializerContexts provided. Did you make any progress yourself? |
That is good to hear. Unfortunately, I did not have any progress myself yet. As it is for a personal (non work-related project), time is currently very limited as I am also in the middle of a home renovation which takes more time to manage than anticipated. However it is quite strange that just referencing the NpmRegistry.Wrapper project (instead of the NuGet package) works when setting the project to .NET10. When looking into it earlier I did the following (next to other things BTW);
This still resulted in the same |
|
I finally had some time to dig into this issue further. I added some additional logging to my code (did not update this repo) to see what could be wrong. Without applying any of your patches, I tried to look into the differences in the runtime when running the task as a standalone application (which succeeds) and running it as an MSBuild task (which fails). To get a clear understanding in the differences, I created the following table:
As can be seen in the table above, when the code is run as an MSBuild task, the The thing that I also see, is that in case it runs as an MSBuild task, all direct assembly references of my Now the question is, why is I will also update my issue on MSBuild with this information. Maybe it will lead to some fix over there. So far I don't see any way to nicely solve it, except by explicitly loading the assembly into the correct load context. |
|
I'm currently away from my machine, but both times it worked for me, I moved the package wrapper into a csproj in the project. If the way nuget and the embedded csproj work in similar ways where the nuget's http json ref goes to the default context whereas the embedded's ref gets loaded in the right context, it would make sense. |
|
Looked into it a bit. Since MSBuild 16, Tasks get their own ALC (AssemblyLoadContext) and they are expected to keep all their dependencies there to avoid any conflicts. Another reason is so you can use different versions of the same lib in different Tasks without conflicts again. In your case, I see one possibly impactful issue. Your task is running out-of-proc due to .net10. I'm also not sure if the wrapper nuget keeps its own dependencies next to it, in the |
First off, I added MessageImportance.High in Log.LogMessage calls because otherwise they are not displayed and debugging becomes difficult.
Second, I noticed that in:
MissingMethodException/Tools/Tasks/UpdateNpmPackages.cs
Lines 115 to 118 in b97ff78
RegistryClient.GetPackageDatais called and Result is asked for instantly when you're supposed to await it.Instead store in Task<NpmPackage?> var and call .Wait(). Probably the reason why it's not always working right.
I tried a few things to get it working with the JsonSerializerContext, but ultimately, I opted to add a local version of the NpmRegistry.Wrapper and try out stuff. One such case was to switch
GetFromJsonAsync(url, context, ...)toGetFromJsonAsync<NpmPackage>(url,...)and it worked, as in it moved on, did not throw the error and tried to get the json data from the registry. But it did fail to get everything correctly. My theory is that it failed to grab fields that were separate classes (DictTags, Versions etc).This part specifically failed because DistTags was null, and because of Log.LogError it failed after just
chart.js:MissingMethodException/Tools/Tasks/UpdateNpmPackages.cs
Lines 122 to 123 in b97ff78
As for the main issue, I think it's because
System.Net.Http.Json, among others, is trimmable (iirc, I saw the it indnspy) and by using the interface to decouple the Task dll from theNpmRegistryClientcode basically hides the json stuff,which likely ends up hiding the call to the assembly, ergo it's trimmed, which also likely ends up trimming types from the
NpmRegistry.Wrapperassembly. One more thing that also nudges me towards the trimmingidea is that
NpmRegistry.Wrapper, uses generators for theJsonSerializerContext(much likeDataTypesandTasks) and they are likely not generated and propagated through the assembly properly (at least when integrated through the nuget package).I looked at the _bin/ folders where other libs have no problem generating their own
JsonSerializerContextclasses, butNpmRegistry.Wrapper's was nowhere to be found.So to try and test this, I added a console app to call the Task directly for a first test, removed the
ModelsSerializerContext, provided my own version ofGetFromJsonAsync, basically a function that downloads the whole response first into a byte array and calls deserialize and it worked. The idea was to remove the dependency to the trimmable function call and also by removing theJsonSerializerContext, remove the problem of the generated files being inaccessible to the Task code on runtime. Got the response for all 4 npm packages, fully deserialized.