在运行时加载nuget依赖项
我正在寻找一种通过执行以下步骤来运行代码的方法:
- 接收NuGet包列表(元组列表(“包名”,“包版本”,“主类路径”)。
- 在本地目录中检索它们(参见代码示例#1)
- 在运行时将它们加载到我的程序中
- 通过内省运行主类(参见代码示例#2)
到现在为止,我正在努力迈出第三步。 我无法在运行时找到如何加载我的包。
我的主要问题是:
- 如何找出存储检索到的包的文件夹?
- 如何将这些目录的内容加载到我的程序中?
谢谢你的帮助。
代码示例#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
下载nuget包的代码片段
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
事件中。
我们如何在隔离的应用程序域中加载程序集?
由于reflectionAPI不提供在特定域中加载程序集的方法,因此我们将创建一个代理类,在我们的隔离域中充当加载器:
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; } } }
而现在,是如何把它们放在一起的?
这是复杂的部分:
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, ""); object instance = domain.CreateInstanceAndUnwrap(type.Assembly.FullName, type.FullName); } catch (Exception ex) { Console.WriteLine("failed to load {0}", file); Console.WriteLine(ex.ToString()); } } }
请注意,此方法是下载nuget包后执行的事件处理程序
也
请注意,您需要将
替换为来自程序集的预期类型名称(或者可能在程序集中运行所有公共类型的发现)
值得注意的是,我自己并没有执行此代码,也无法保证它能够开箱即用,仍然可能需要进行一些调整。 但希望它是允许您解决问题的概念。
不要那样做! 您可能正在尝试在客户计算机上加载nugets以节省一些软件分发空间。 不是吗?
常见的推荐方法是下载nuget作为自动构建的第二步(下载源代码后),构建软件并使用已下载的nugets运行自动化测试。 然后使用您测试过的复杂整体单元分配构建。