PostBuild事件中的.NET Core Assembly.LoadFile

max*_*her 9 .net c# .net-core asp.net-core

我需要typescript在构建之后从我的一些C#类生成文件.

我创建dotnet cli tool并添加了post-build事件

dotnet tsgenerator "$(TargetPath)"
Run Code Online (Sandbox Code Playgroud)

$(TargetPath)例如,宏在哪里指向D:\Test\bin\Release\netcoreapp2.0\my.dll

接下来,我尝试下一步加载程序集:

public static void Main(string[] args)
{
    var dllPath = args[0]; // "D:\Test\bin\Release\netcoreapp2.0\my.dll"
    var assembly = Assembly.LoadFile(dllPath);
    var types = assembly.GetExportedTypes(); // Throws exception
}
Run Code Online (Sandbox Code Playgroud)

但我得到了ReflectionTypeLoadException,说Could not load file or assembly了一些参考组件(例如,Microsoft.AspNetCore.Antiforgery).

我如何为.NET Core应用程序加载程序集?

max*_*her 5

我在github问题上找到了解决方案.amits1995angelcalvasp的消息.

我已添加<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>到我的csproj并使用此代码加载程序集:

public static class AssemblyLoader
{
    public static Assembly LoadFromAssemblyPath(string assemblyFullPath)
    {
        var fileNameWithOutExtension = Path.GetFileNameWithoutExtension(assemblyFullPath);
        var fileName = Path.GetFileName(assemblyFullPath);
        var directory = Path.GetDirectoryName(assemblyFullPath);

        var inCompileLibraries = DependencyContext.Default.CompileLibraries.Any(l => l.Name.Equals(fileNameWithOutExtension, StringComparison.OrdinalIgnoreCase));
        var inRuntimeLibraries = DependencyContext.Default.RuntimeLibraries.Any(l => l.Name.Equals(fileNameWithOutExtension, StringComparison.OrdinalIgnoreCase));

        var assembly = (inCompileLibraries || inRuntimeLibraries)
            ? Assembly.Load(new AssemblyName(fileNameWithOutExtension))
            : AssemblyLoadContext.Default.LoadFromAssemblyPath(assemblyFullPath);

        if (assembly != null)
            LoadReferencedAssemblies(assembly, fileName, directory);

        return assembly;
    }

    private static void LoadReferencedAssemblies(Assembly assembly, string fileName, string directory)
    {
        var filesInDirectory = Directory.GetFiles(directory).Where(x => x != fileName).Select(x => Path.GetFileNameWithoutExtension(x)).ToList();
        var references = assembly.GetReferencedAssemblies();

        foreach (var reference in references)
        {
            if (filesInDirectory.Contains(reference.Name))
            {
                var loadFileName = reference.Name + ".dll";
                var path = Path.Combine(directory, loadFileName);
                var loadedAssembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(path);
                if (loadedAssembly != null)
                    LoadReferencedAssemblies(loadedAssembly, loadFileName, directory);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

public static void Main(string[] args)
{
    var dllPath = args[0]; // "D:\Test\bin\Release\netcoreapp2.0\my.dll"
    var assembly = AssemblyLoader.LoadFromAssemblyPath(dllPath);
    var types = assembly.GetExportedTypes(); // No exceptions
}
Run Code Online (Sandbox Code Playgroud)