PowerShell:PowerShell如何实例化C#类

时间:2014-01-28 00:02:56

标签: c# powershell

最初,我认为只有在调用此类上标记的cmdlet时,PowerShell才会实例化一个类。执行时,每个cmdlet都属于BeginProcess - > ProcessRecord - > EndProcess(StopProcess)路径,在EndProcess完成之后,似乎进程将结束,然后内存将所有这些类对象收集为垃圾。因此每个类应该存在于自己的生命周期中而不共享任何资源。当我们调用这些cmdlet时,

但是我发现类在同一个模块中共享相同的静态值。例如,假设在我的项目中我有两个类:

namespace PSDSL
{
    [Cmdlet(VerbsCommon.Get, "MyTest")]
    public class GetMyTest : Cmdlet
    {
        public static GlobalUserName = "";
        [Parameter(Mandatory = false)]
        public string Filepath { get; set; }
        protected override void InnerProcessRecord()
        {
            if (_filepath != null)
            {
                GlobalUserName = _filepath;
            }
             Console.WriteLine(GlobalUserName);
        }
    }
}

namespace PSDSL
{
    [Cmdlet(VerbsCommon.Get, "MyTest2")]
    public class GetMyTest2 : Cmdlet
    {
        [Parameter(Mandatory = false)]
        public string Filepath { get; set; }
        protected override void InnerProcessRecord()
        {
            if (_filepath != null)
            {
                GlobalUserName = _filepath;
            }
             Console.WriteLine(GlobalUserName);
        }
    }
}

除了定义静态GlobalUserName之外,这两个命令非常相似。调用这两个cmdlet表示可以从两个cmdlet读取/写入GlobalUserName。

我的困惑在于,什么时候课程会被实现?

1 个答案:

答案 0 :(得分:2)

立即加载整个程序集并保持加载状态,直到重新启动PowerShell提示符。

<强>详细信息:

.Net中最小的代码隔离单元是Assembly(在大多数情况下是单个托管DLL)。

使用托管运行时的进程一次加载的次数少于单个程序集 - 因此该程序集中的所有类(以及相关的一次性请求)将一起加载。因此,所有静态字段将同时出现在内存中(请注意,静态字段在首次使用类之前初始化“,这意味着它们不必在程序集加载时初始化)。

如果不使用单独的AppDomain,也无法“卸载”类甚至程序集。 PowerShell不使用多个AppDomain来加载不同模块的程序集(通常在实现过程中需要特别注意交叉AddDomain调用,现在你已经了解它)。结果一旦加载模块保留在内存中,直到您退出PowerShell(Powershell Unload Module... completely中所述)。

由于程序集为其中的所有命令行开关加载一次,所有静态字段将立即出现并保持值直到退出PowerShell。

附注:我强烈建议避免使用static字段,除了一般的静态不可变数据。这是容易在那里留下一些随机值并影响未来代码的方法。在PowerShell管道中是在命令行开关之间传递信息的方式,其他类型的进程(WinForms,ASP.Net,...)有他们自己的首选机制来传递数据而不是使用静态。