Load nuget dependencies at runtime

浪子不回头ぞ 提交于 2019-11-30 06:51:22
Bishoy

Grab a cup of coffee :)

Downloading the nuget package?

Nuget.Core (nuget package) is a good choice, and here is a snippet of code that I have that should be able to download a nuget package by id and version

var repo = PackageRepositoryFactory.Default
                .CreateRepository("https://packages.nuget.org/api/v2");

string path = "c:\\temp";
var packageManager = new PackageManager(repo, path);
packageManager.PackageInstalled += PackageManager_PackageInstalled;

var package = repo.FindPackage("packageName", SemanticVersion.Parse("1.0.0"));
if (package != null)
{
    packageManager.InstallPackage(package, false, true);
}

Notice that I plugged an event handler to the PackageInstalled event of the PackageManager class.

How do we load an assembly in an isolated app domain?

Since reflection API does not provide a way to load an assembly in a specific domain, We will create a proxy class that act as a loader in our isolated domain:

public class TypeProxy : MarshalByRefObject
{
    public Type LoadFromAssembly(string assemblyPath, string typeName)
    {
        try
        {
            var asm = Assembly.LoadFile(assemblyPath);
            return asm.GetType(typeName);
        }
        catch (Exception) { return null; }
    }
}

And now, is how to put it all together?

Here comes the complex part:

private static void PackageManager_PackageInstalled(object sender, 
                                                    PackageOperationEventArgs e)
{
    var files = e.FileSystem.GetFiles(e.InstallPath, "*.dll", true);
    foreach (var file in files)
    {
        try
        {
            AppDomain domain = AppDomain.CreateDomain("tmp");
            Type typeProxyType = typeof(TypeProxy);
            var typeProxyInstance = (TypeProxy)domain.CreateInstanceAndUnwrap(
                    typeProxyType.Assembly.FullName,
                    typeProxyType.FullName);

            var type = typeProxyInstance.LoadFromAssembly(file, "<KnownTypeName>");
            object instance = 
                domain.CreateInstanceAndUnwrap(type.Assembly.FullName, type.FullName);
        }
        catch (Exception ex)
        {
            Console.WriteLine("failed to load {0}", file);
            Console.WriteLine(ex.ToString());
        }

    }
}

Notice that this method is the event handler that gets executed after downloading the nuget package

Also

Note that you will need to replace <KnownTypeName> with the expected type name coming from the assembly (or maybe run a discovery of all public types in the assembly)


Worth noting that I haven't executed this code myself and cannot guarantee that it will work out of the box, and still might need some tweaking. but Hopefully it is the concept that allows you to solve the problem.

Don't do that! You are probably trying to load nugets at customers computer to save some space on distribution of your software. Isn't it that?

Common recommended approach is to download the nuget as the second step of automated build (after downloading source code), build the software and run the automated tests with nugets you have downloaded. And then distribute the build with nugets you have tested as the complex whole unit.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!