UserPrincipal.Save()导致ObjectDisposedException

时间:2012-08-31 22:18:28

标签: c# .net active-directory

请考虑我拥有的Active Directory服务中的以下代码段。在Rename()方法中,它始终抛出ObjectDisposedException,“无法访问已处置的对象。对象名称:'DirectoryEntry'。

这曾经工作正常,但我也有一个Add()方法,两者的代码是95%相同。所以,我选择了SetIdentity()方法,我将传递主体和属性字典并从那里开始。 Add()方法有效,但那是因为还没有底层对象可以操作。 Rename()方法失败,因为有一个。

我知道如果我将SetIdentity()的代码放回Rename(),它会正常工作,但我不想这样做。

我已尝试在using块中Rename()中包装try/catch子句,但它没有做任何事情。我试过通过ref传递校长和字典,但这也没有帮助。我已经尝试检查DirectoryEntry是否为空,但没有帮助。

所以,我猜它不能是using子句中失败的代码。我还应该寻找什么?

使用Visual Studio进行调试时,我可以将鼠标悬停在对象上,它就在那里并完成了属性和值,所以我不知道我应该在哪里看...

public override void Rename(
    UserPrincipal principal,
    IDictionary<string, object> properties) {
    if (principal != null) {
        this.SetIdentity(ref principal, ref properties);

        using (DirectoryEntry entry = (principal.GetUnderlyingObject() as DirectoryEntry)) {
            entry.Rename(newName: String.Format("CN={0}", principal.DisplayName));
            entry.CommitChanges();
        };

        principal.Save(); // this is where ASP.NET runtime points to when failed
    };
} // this is where Visual Studio points to when debugging

internal void SetIdentity(
    ref UserPrincipal principal,
    ref IDictionary<string, object> properties) {
    object obj = null;
    string displayName = string.Empty;
    string givenName = string.Empty;
    string middleName = string.Empty;
    string samAccountName = string.Empty;
    string surname = string.Empty;

    if (properties.TryGetValue("GivenName", out obj)) {
        givenName = (string)properties["GivenName"];
    };

    if (properties.TryGetValue("MiddleName", out obj)) {
        middleName = (string)properties["MiddleName"];
    };

    if (properties.TryGetValue("Surname", out obj)) {
        surname = (string)properties["Surname"];
    };

    if (properties.TryGetValue("SamAccountName", out obj)) {
        samAccountName = (string)properties["SamAccountName"];
    };

    if (String.IsNullOrEmpty(middleName)) {
        displayName = String.Format("{0} {1}", givenName, surname);

        if (String.IsNullOrEmpty(samAccountName)) {
            samAccountName = String.Format("{0}{1}", givenName[0], surname);
        };
    } else {
        displayName = String.Format("{0} {1}. {2}", givenName, middleName[0], surname);

        if (String.IsNullOrEmpty(samAccountName)) {
            samAccountName = String.Format("{0}{1}{2}", givenName[0], middleName[0], surname);
        };
    };

    samAccountName = samAccountName.ToLower();

    principal.DisplayName = displayName;
    principal.GivenName = givenName;
    principal.MiddleName = middleName;
    principal.SamAccountName = samAccountName;
    principal.Surname = surname;
    principal.UserPrincipalName = String.Format("{0}@dryforce.com", samAccountName);
}

1 个答案:

答案 0 :(得分:6)

   using (DirectoryEntry entry = (principal.GetUnderlyingObject() as DirectoryEntry))

为.NET设计师购买一支雪茄,以获得良好的方法命名。您正在使用using语句处理“底层对象”。你猛地踩下地板垫,使得班级工作的对象不复存在。这是一只死鹦鹉。相当于处理StreamReader.BaseStream。在你这样做之后试图从它上面读取Kaboom,无法从被处置的底层物体中读取。

处理它不是你的工作,你的代码没有创建它。通过省略 using 关键字来解决问题。