在运行时加载NuGet依赖项 [英] Load NuGet dependencies at runtime
问题描述
我正在寻找一种通过执行以下步骤来运行代码的方法:
I'm looking for a way to run code by executing the following steps:
- 接收NuGet软件包列表(列表元组(程序包名称,程序包版本,主类的路径)。
- 在本地目录中检索它们(参见代码示例1)
- 在运行时将它们加载到我的程序中
- 通过自省运行主要类(参见代码示例2)
- 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.
我的主要问题是:
- 如何找出检索到的软件包存储在哪个文件夹中?
- 如何将那些目录的内容加载到程序中?
代码示例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屋!