Usefull.PullPackage
1.3.5
dotnet add package Usefull.PullPackage --version 1.3.5
NuGet\Install-Package Usefull.PullPackage -Version 1.3.5
<PackageReference Include="Usefull.PullPackage" Version="1.3.5" />
<PackageVersion Include="Usefull.PullPackage" Version="1.3.5" />
<PackageReference Include="Usefull.PullPackage" />
paket add Usefull.PullPackage --version 1.3.5
#r "nuget: Usefull.PullPackage, 1.3.5"
#addin nuget:?package=Usefull.PullPackage&version=1.3.5
#tool nuget:?package=Usefull.PullPackage&version=1.3.5
Usefull.PullPackage
.NET library for pulling NuGet packages and loading them dynamically in runtime.
Basic usage
Install NuGet package:
dotnet add package Usefull.PullPackage
Add using derective:
using Usefull.PullPackage;
Configure and build puller object:
using var puller = Puller.Build(config => config
.Framework(FrameworkMoniker.net8_0) // set target framework version
.Package("System.Text.Json", "9.0.1") // define packages to pull
.Package("Humanizer.Core", "2.14.1")
.Package("Npgsql", "9.0.2")
.Source("local", "E:\\Work\\VisualStudio\\HDS\\.net\\.nuget\\") // define local folder source
.WithMapping("Humanizer.Core") // define package which will be pulled from this source
.Source("nuget.org", "https://api.nuget.org/v3/index.json") // define nuget.org source
.WithMapping("*") // all other packages will be pulled from nuget.org
.Directory("E:\\_TEMP\\") // set target directory to pull
);
Perform pulling:
await puller.PullAsync();
Load all pulled assemblies:
var ctx = puller.LoadAll();
Then you can use loaded assemblies functionality by scripting:
using Microsoft.CodeAnalysis.CSharp.Scripting;
...
// Build script options and define imports (usings) for script
var options = ctx.BuildScriptOptions()
.AddImports("System", "Humanizer");
// Invoke script and get result
var result = await CSharpScript.RunAsync("DateTime.UtcNow.AddHours(-2).Humanize()", options);
Or you can use it by reflection:
// Find assembly System.Text.Json.dll in pulled packages
var textJsonAssembly = ctx.GetAssemblies()
.FirstOrDefault(a => a.FullName?.Contains("Text.Json") ?? false);
// Get type System.Text.Json.JsonSerializer
var jsonSerializerType = textJsonAssembly?.GetType("System.Text.Json.JsonSerializer");
// Get type System.Text.Json.JsonSerializerOptions
var jsonSerializerOptionsType = textJsonAssembly?.GetType("System.Text.Json.JsonSerializerOptions");
// Create instance of System.Text.Json.JsonSerializerOptions
var jsonSerializerOptions = Activator.CreateInstance(jsonSerializerOptionsType);
// Find method System.Text.Json.JsonSerializer.Serialize(object, Type, JsonSerializerOptions)
var serializeMethod = jsonSerializerType.GetMethod("Serialize", [typeof(object), typeof(Type), jsonSerializerOptionsType]);
// Invoke method
var result = serializeMethod.Invoke(null, [new Entity { Name = "Some entity", Value = 12 }, typeof(Entity), jsonSerializerOptions]);
Simplified usage by reflection:
// Attempt to create an instance of NpgsqlDataSourceBuilder
var dataSourceBuilder = ctx.CreateInstance(
"Npgsql.NpgsqlDataSourceBuilder",
["Host=psqlhost;Port=5432;Username=user;Database=data;Password=pass"]);
// Build PostgreSQL data source and open connection
var dataSource = dataSourceBuilder.GetType().GetMethod("Build").Invoke(dataSourceBuilder, null);
var connection = dataSource.GetType().GetMethod("OpenConnection").Invoke(dataSource, null);
Unloading the context after use
In order to be able to unload after use, it is necessary to load assemblies into a �ollectible context:
var ctx = puller.LoadAll(true);
When the context is no longer needed initiate unloading by calling:
ctx.Unload();
However, this does not guarantee immediate release of the memory occupied by the context. To force unloading, use the following technique:
- First, wrap all context operations, starting with loading, inside a single non-asynchronous method. Mark the method with an attribute MethodImplAttribute. This method, in addition to the necessary results, should return a weak reference to the context. For example, like this:
[MethodImpl(MethodImplOptions.NoInlining)]
private static (List<string>, WeakReference) GetAssembles(Puller puller)
{
// Load all pulled assemblies
var ctx = puller.LoadAll(true);
// Read assemblies location.
var result = puller.Packages.SelectMany(a => a.RuntimeAssemblies)
.Select(a => a.Path).ToList();
// Unload context
ctx.Unload();
// Return result and the context weak redference
return (result, new WeakReference(ctx));
}
- After disposing the puller, force an immediately garbage collection and wait for the context finalized:
using (var puller = Puller.Build( ... ))
{
await puller.PullAsync();
// Do the necessary work with the context
(var assys, ctxRef) = GetAssembles(puller);
foreach(var assy in assys)
Console.WriteLine(assy);
}
// Waiting for the context finalized
while (ctxRef.IsAlive)
{
GC.Collect();
GC.WaitForPendingFinalizers();
}
Under certain conditions, the described approach allows for the complete unloading of the context. For more details see "Use collectible AssemblyLoadContext".
A full usage examples are available in our repository.
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net5.0 is compatible. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
.NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
.NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
.NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
MonoAndroid | monoandroid was computed. |
MonoMac | monomac was computed. |
MonoTouch | monotouch was computed. |
Tizen | tizen40 was computed. tizen60 was computed. |
Xamarin.iOS | xamarinios was computed. |
Xamarin.Mac | xamarinmac was computed. |
Xamarin.TVOS | xamarintvos was computed. |
Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Microsoft.CodeAnalysis.Scripting.Common (>= 4.5.0)
- NuGet.Commands (>= 6.14.0)
- System.Runtime.Loader (>= 4.3.0)
- System.Text.Json (>= 9.0.5)
-
net5.0
- Microsoft.CodeAnalysis.Scripting.Common (>= 4.5.0)
- NuGet.Commands (>= 6.14.0)
- System.Runtime.Loader (>= 4.3.0)
- System.Text.Json (>= 9.0.5)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.