在运行时加载NuGet依赖项 [英] Load NuGet dependencies at runtime

查看:145
本文介绍了在运行时加载NuGet依赖项的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一种通过执行以下步骤来运行代码的方法:

I'm looking for a way to run code by executing the following steps:


  1. 接收NuGet软件包列表(列表元组(程序包名称,程序包版本,主类的路径)。

  2. 在本地目录中检索它们(参见代码示例1)

  3. 在运行时将它们加载到我的程序中

  4. 通过自省运行主要类(参见代码示例2)

  1. Receiving a list of NuGet packages (a list of tuples ("package name", "package version", "path to main class").
  2. Retrieving them in a local directory (cf code sample #1)
  3. Loading them in my program at run-time
  4. Running the main classes by introspection (cf code sample #2)

现在,我正在为第三步苦苦挣扎。我找不到如何在运行时加载程序包的方法。

By now I am struggling with the third step. I can't find out how to load my package at run-time.

我的主要问题是:


  • 如何找出检索到的软件包存储在哪个文件夹中?

  • 如何将那些目录的内容加载到程序中?

代码示例1:

private static void getPackageByNameAndVersion(string packageID, string version)
{
    IPackageRepository repo =
            PackageRepositoryFactory.Default
                  .CreateRepository("https://packages.nuget.org/api/v2");

   string path = "C:/tmp_repo";
   PackageManager packageManager = new PackageManager(repo, path);
   Console.WriteLine("before dl pkg");
   packageManager.InstallPackage(packageID, SemanticVersion.Parse(version));

}

代码示例2:

private static void loadByAssemblyNameAndTypeName(string assemblyName, string typeName)
{
   AppDomain isolationAppDomain = AppDomain.CreateDomain("tmp");
   object a = isolationAppDomain.CreateInstanceAndUnwrap(assemblyName, typeName);
   Type x = a.GetType();
   MethodInfo m = x.GetMethod("Main");
   m.Invoke(a, new object[] { });
}


推荐答案

抢一杯咖啡: )



正在下载nuget软件包吗?



Nuget.Core(nuget软件包)是一个不错的选择,在这里是我拥有的一小段代码,应该可以通过 id version

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);
}




请注意,我将事件处理程序插入了 PackageManager 类的 PackageInstalled 事件。



我们如何在隔离的应用程序域中加载程序集?



由于反射API无法提供在特定域中加载程序集的方法,我们将在我们的隔离域中创建一个充当加载程序的代理类:

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());
        }

    }
}




请注意,此方法是在下载nuget程序包后执行的事件处理程序

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


请注意,您需要将< KnownTypeName> 替换为来自程序集的预期类型名称(或者可能会发现程序集中的所有公共类型)

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)






值得一提的是,我还没有亲自执行此代码,因此不能保证它会立即可用,仍然可能需要进行一些调整。但是希望它是可以解决问题的概念。

这篇关于在运行时加载NuGet依赖项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆