1

私が持っている Active Directory サービスの次のコードを考えてみましょう。このメソッドでは、常に「破棄されたオブジェクトにアクセスできません。オブジェクト名: 'DirectoryEntry'.Rename()がスローされます。ObjectDisposedException

これは以前は正常に機能していましたが、Add()メソッドもあり、2 つのコードは 95% 同一のコードでした。そこで、SetIdentity()プリンシパルとプロパティ ディクショナリを渡してそこから移動する方法を選択しました。メソッドは機能しますが、それAdd()は操作する基になるオブジェクトがまだないためです。1 つあるため、Rename()メソッドは失敗します。

コードをSetIdentity()元に戻せばRename()問題なく動作することはわかっていますが、そうしたくありません。

using句をRename()ブロックでラップしようとしましたtry/catchが、何もしませんでした。でプリンシパルと辞書を渡そうとしましたrefが、それも役に立ちませんでした。が nullかどうかを確認しようとしました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);
}
4

1 に答える 1

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

.NET 設計者には、良いメソッドの命名のために葉巻を購入してください。using ステートメントで「基になるオブジェクト」を破棄しています。あなたはフロアマットを引っ張った、クラスを機能させるオブジェクトはもうありません。死んだオウムです。これに相当するのは、StreamReader.BaseStream を破棄することです。それを行った後にそれを読み取ろうとすると、Kaboom になり、破棄された基になるオブジェクトから読み取ることができません。

それを処分するのはあなたの仕事ではありません。あなたのコードはそれを作成しませんでした。usingキーワードを省略して問題を修正します。

于 2012-08-31T23:06:57.837 に答える