在运行时加载 NuGet 依赖项
Load NuGet dependencies at runtime
我正在寻找一种通过执行以下步骤来 运行 代码的方法:
- 正在接收 NuGet 包列表(元组列表 ("package name"、"package version"、"path to main class")。
- 在本地目录中检索它们(参见代码示例 #1)
- 在 运行-time
将它们加载到我的程序中
- 运行 主要 类 内省(参见代码示例 #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);
}
Notice that I plugged an event handler to the PackageInstalled
event of the PackageManager
class.
我们如何在独立的应用程序域中加载程序集?
由于反射 API 不提供在特定域中加载程序集的方法,我们将创建一个代理 class 作为我们隔离域中的加载程序:
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, "<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
还有
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 内容以节省一些 space 软件分发费用。不是吗?
通常推荐的方法是下载 NuGet 内容作为自动构建的第二步(在下载源代码之后),使用您下载的 NuGet 内容构建软件和运行 自动化测试.然后分发包含您测试过的 NuGet 内容的构建作为复杂的整体单元。
我正在寻找一种通过执行以下步骤来 运行 代码的方法:
- 正在接收 NuGet 包列表(元组列表 ("package name"、"package version"、"path to main class")。
- 在本地目录中检索它们(参见代码示例 #1)
- 在 运行-time 将它们加载到我的程序中
- 运行 主要 类 内省(参见代码示例 #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);
}
Notice that I plugged an event handler to the
PackageInstalled
event of thePackageManager
class.
我们如何在独立的应用程序域中加载程序集?
由于反射 API 不提供在特定域中加载程序集的方法,我们将创建一个代理 class 作为我们隔离域中的加载程序:
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, "<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
还有
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 内容以节省一些 space 软件分发费用。不是吗?
通常推荐的方法是下载 NuGet 内容作为自动构建的第二步(在下载源代码之后),使用您下载的 NuGet 内容构建软件和运行 自动化测试.然后分发包含您测试过的 NuGet 内容的构建作为复杂的整体单元。