Sco*_*ein 4 powershell code-generation powershell-2.0
我正在开发一个生成CSharp代码的PoSh项目,然后将Add-Type其放入内存中.
新类型使用磁盘DLL中的现有类型,该DLL通过Add-Type加载.
一切都很好,直到我实际上尝试调用新类型的方法.这是我正在做的一个例子:
$PWD = "."
rm -Force $PWD\TestClassOne*
$code = "
namespace TEST{
public class TestClassOne
{
public int DoNothing()
{
return 1;
}
}
}"
$code | Out-File tcone.cs
Add-Type -OutputAssembly $PWD\TestClassOne.dll -OutputType Library -Path $PWD\tcone.cs
Add-Type -Path $PWD\TestClassOne.dll
$a = New-Object TEST.TestClassOne
"Using TestClassOne"
$a.DoNothing()
"Compiling TestClassTwo"
Add-Type -Language CSharpVersion3 -TypeDefinition "
namespace TEST{
public class TestClassTwo
{
public int CallTestClassOne()
{
var a = new TEST.TestClassOne();
return a.DoNothing();
}
}
}" -ReferencedAssemblies $PWD\TestClassOne.dll
"OK"
$b = New-Object TEST.TestClassTwo
"Using TestClassTwo"
$b.CallTestClassOne()
Run Code Online (Sandbox Code Playgroud)
运行上面的脚本在最后一行给出以下错误:
使用"0"参数调用"CallTestClassOne"的异常:"无法加载文件或程序集'TestClassOne,...'或其依赖项之一.系统无法找到指定的文件." 在AddTypeTest.ps1:39 char:20 + $ b.CallTestClassOne <<<<()+ CategoryInfo:NotSpecified:(:) [],MethodInvocationException + FullyQualifiedErrorId:DotNetMethodException
我究竟做错了什么?
发生这种情况是因为应用程序(PowerShell)基目录中的CLR加载程序会查找任何程序集.当然,它没有在那里找到你的组装.解决此问题的最佳方法是将AssemblyResolve事件挂钩为stej提及,但使用它来告诉CLR程序集所在的位置.您无法使用PowerShell 2.0的Register-ObjectEvent执行此操作,因为它不适用于需要返回值的事件(即程序集).在这种情况下,让我们通过Add-Type使用更多C#来为我们完成这项工作.这段代码有效:
ri .\TestClassOne.dll -for -ea 0
$resolver = @'
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
namespace Utils
{
public static class AssemblyResolver
{
private static Dictionary<string, string> _assemblies;
static AssemblyResolver()
{
var comparer = StringComparer.CurrentCultureIgnoreCase;
_assemblies = new Dictionary<string,string>(comparer);
AppDomain.CurrentDomain.AssemblyResolve += ResolveHandler;
}
public static void AddAssemblyLocation(string path)
{
// This should be made threadsafe for production use
string name = Path.GetFileNameWithoutExtension(path);
_assemblies.Add(name, path);
}
private static Assembly ResolveHandler(object sender,
ResolveEventArgs args)
{
var assemblyName = new AssemblyName(args.Name);
if (_assemblies.ContainsKey(assemblyName.Name))
{
return Assembly.LoadFrom(_assemblies[assemblyName.Name]);
}
return null;
}
}
}
'@
Add-Type -TypeDefinition $resolver -Language CSharpVersion3
$code = @'
namespace TEST {
public class TestClassOne {
public int DoNothing() {
return 1;
}
}
}
'@
$code | Out-File tcone.cs
Add-Type -OutputAssembly TestClassOne.dll -OutputType Library -Path tcone.cs
# This is the key, register this assembly's location with our resolver utility
[Utils.AssemblyResolver]::AddAssemblyLocation("$pwd\TestClassOne.dll")
Add-Type -Language CSharpVersion3 `
-ReferencedAssemblies "$pwd\TestClassOne.dll" `
-TypeDefinition @'
namespace TEST {
public class TestClassTwo {
public int CallTestClassOne() {
var a = new TEST.TestClassOne();
return a.DoNothing();
}
}
}
'@
$b = new-object Test.TestClassTwo
$b.CallTestClassOne()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6088 次 |
| 最近记录: |