Load NuGet dependencies at runtime(在运行时加载 NuGet 依赖项)
问题描述
我正在寻找一种通过执行以下步骤来运行代码的方法:
- 接收 NuGet 包列表(元组列表(包名称"、包版本"、主类路径").
- 在本地目录中检索它们(参见代码示例 #1)
- 在运行时将它们加载到我的程序中
- 通过自省运行主类(参见代码示例 #2)
现在我正在努力完成第三步.我不知道如何在运行时加载我的包.
我的主要问题是:
- 如何知道检索到的包存放在哪些文件夹中?
- 如何将这些目录的内容加载到我的程序中?
代码示例 #1:
private static void getPackageByNameAndVersion(string packageID, string version){IPackageRepository 回购 =PackageRepositoryFactory.Default.CreateRepository("https://packages.nuget.org/api/v2");字符串路径 = "C:/tmp_repo";PackageManager packageManager = new PackageManager(repo, path);Console.WriteLine("在 dl pkg 之前");packageManager.InstallPackage(packageID, SemanticVersion.Parse(version));}
代码示例 #2:
private static void loadByAssemblyNameAndTypeName(string assemblyName, string typeName){AppDomain 隔离AppDomain = AppDomain.CreateDomain("tmp");对象 a =isolationAppDomain.CreateInstanceAndUnwrap(assemblyName, typeName);类型 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");字符串路径 = "c:\temp";var packageManager = new PackageManager(repo, path);packageManager.PackageInstalled += PackageManager_PackageInstalled;var package = repo.FindPackage("packageName", SemanticVersion.Parse("1.0.0"));如果(包!= null){packageManager.InstallPackage(package, false, true);}
<块引用>
请注意,我在 PackageManager
类的 PackageInstalled
事件中插入了一个事件处理程序.
我们如何在隔离的应用程序域中加载程序集?
由于反射 API 不提供在特定域中加载程序集的方法,我们将创建一个代理类,作为我们隔离域中的加载器:
公共类 TypeProxy : MarshalByRefObject{公共类型 LoadFromAssembly(字符串 assemblyPath,字符串 typeName){尝试{var asm = Assembly.LoadFile(assemblyPath);返回 asm.GetType(typeName);}捕捉(异常){返回null;}}}
现在,如何将它们组合在一起?
复杂的部分来了:
private static void PackageManager_PackageInstalled(object sender,PackageOperationEventArgs e){var files = e.FileSystem.GetFiles(e.InstallPath, "*.dll", true);foreach(文件中的 var 文件){尝试{AppDomain 域 = AppDomain.CreateDomain("tmp");类型 typeProxyType = typeof(TypeProxy);var typeProxyInstance = (TypeProxy)domain.CreateInstanceAndUnwrap(typeProxyType.Assembly.FullName,typeProxyType.FullName);var type = typeProxyInstance.LoadFromAssembly(file, "<KnownTypeName>");对象实例 =domain.CreateInstanceAndUnwrap(type.Assembly.FullName, type.FullName);}捕捉(例外前){Console.WriteLine("未能加载 {0}", file);Console.WriteLine(ex.ToString());}}}
<块引用>
注意这个方法是下载nuget包后执行的事件处理程序
还有
<块引用>请注意,您需要将 <KnownTypeName>
替换为来自程序集的预期类型名称(或者可能运行程序集中所有公共类型的发现)
<小时>
值得注意的是,我自己还没有执行过这段代码,也不能保证它可以开箱即用,可能还需要一些调整.但希望它是可以让您解决问题的概念.
I'm looking for a way to run code by executing the following steps:
- Receiving a list of NuGet packages (a list of tuples ("package name", "package version", "path to main class").
- Retrieving them in a local directory (cf code sample #1)
- Loading them in my program at run-time
- 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.
My main question are:
- How can I find out in which folders were stored the retrieved packages?
- How can I load the content of those directories into my program?
Code Sample #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));
}
Code sample #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[] { });
}
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 thePackageManager
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.
这篇关于在运行时加载 NuGet 依赖项的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:在运行时加载 NuGet 依赖项
基础教程推荐
- 为什么Flurl.Http DownloadFileAsync/Http客户端GetAsync需要 2022-09-30
- MS Visual Studio .NET 的替代品 2022-01-01
- SSE 浮点算术是否可重现? 2022-01-01
- 如何在 IDE 中获取 Xamarin Studio C# 输出? 2022-01-01
- 有没有办法忽略 2GB 文件上传的 maxRequestLength 限制? 2022-01-01
- 将 XML 转换为通用列表 2022-01-01
- rabbitmq 的 REST API 2022-01-01
- 将 Office 安装到 Windows 容器 (servercore:ltsc2019) 失败,错误代码为 17002 2022-01-01
- 如何激活MC67中的红灯 2022-01-01
- c# Math.Sqrt 实现 2022-01-01