正确的方法从另一个使用statment包含的类中撤回数据

HiT*_*ech 3 c# using-statement winforms

我得到一个例外"无法访问已处置的对象.".我知道我得到了这个例外,因为在它有机会返回结果之前,该对象已被删除.我想知道的是什么是撤回物体的正确方法.我可能在我的代码中有不必要的步骤,可能这样做错了吗?

所以我在我的主课堂上有一个按钮点击事件.它调用下面代码中显示的方法.GetADComputer方法位于另一个名为ActiveDirectory.cs的类(我创建了一个类文件.cs)中.我在尝试访问被驱散对象的结果时发现了异常.

public static PrincipalSearchResult<Principal> GetADComputer(string pcName)
    {
        using (PrincipalContext ctx = new PrincipalContext(ContextType.Domain))
        {
            using (ComputerPrincipal computer = new ComputerPrincipal(ctx))
            {
                computer.Name = String.Format("*{0}*", pcName);

                using (PrincipalSearcher searcher = new PrincipalSearcher())
                {
                    searcher.QueryFilter = computer;
                    return searcher.FindAll();
                }
            }
        }            
    }    
Run Code Online (Sandbox Code Playgroud)

Sco*_*ain 5

问题是DirectoryServices使用Lazy Loading来获取它的信息,所以因为你关闭了上下文,所以你无法再从中检索信息Principal.

您有两个选项,或者将PrincipalContext查询传递给查询,以便在返回时不会超出范围:

public static DoSomthing()
{
    using(var ctx = new PrincipalContext(ContextType.Domain))
    using(PrincipalSearchResult<Principal> result = GetADComputer("some Name", ctx))
    {
        //do something with the result here.
    }
}

public static PrincipalSearchResult<Principal> GetADComputer(string pcName, PrincipalContext ctx)
{
    using (var computer = new ComputerPrincipal(ctx))
    {
        computer.Name = String.Format("*{0}*", pcName);

        using (var searcher = new PrincipalSearcher())
        {
            searcher.QueryFilter = computer;
            return searcher.FindAll();
        }
    }
} 
Run Code Online (Sandbox Code Playgroud)

或者,您需要将结果转换为不依赖于延迟加载的内容,以便关闭与目录服务器的连接.

public static List<ComputerInfo> GetADComputer(string pcName, PrincipalContext ctx)
{
    using (var computer = new ComputerPrincipal(ctx))
    {
        computer.Name = String.Format("*{0}*", pcName);

        using (var searcher = new PrincipalSearcher())
        {
            searcher.QueryFilter = computer;
            using (PrincipalSearchResult<Principal> result = searcher.FindAll())
            {
                return result.Select(p=> new ComputerInfo(p.Name, p.SID)).ToList();
            }
        }
    }
} 

public class ComputerInfo
{
    public ComputerInfo(string name, SecurityIdentifier sid)
    {
        Name = name;
        SID = sid;
    }

    public string Name {get; set;}
    public SecurityIdentifier SID {get; set;}
}
Run Code Online (Sandbox Code Playgroud)