7

イテレータブロックを使用して次を返す単純なメソッドがありますIEnumerable<T>

IEnumerable<MyItem> GetItems()
{
    foreach (var item in Items)
    {
        yield return item;
    }
}

通常、このメソッドは正常に動作し[SecurityCritical]ますが、アセンブリ (または上記のメソッドを含むクラス) に属性を適用するTypeLoadExceptionと、メソッドを呼び出そうとすると がスローされます。読み込みに失敗している型は、反復子メソッドに対応するコンパイラ生成クラスであり、GetEnumeratorセキュリティが透過的であるため、問題の原因となっているのはそのメソッドです。

比較のために、上記のメソッドを変更して を入力して返すとList<MyItem>、すべて正常に動作します。

助言がありますか?

ありがとう、

ティム。

4

3 に答える 3

3

複雑なアプリケーションで、まったく同じ問題がありました。Spring は間に来て、「blahblah」型はそうではなくSerializable、それが正しいと確信していると述べました。これは、コンパイラによって生成されたコードの逆アセンブル コードであり、シリアライズ可能ではないことを確認してください。たぶんこれもあなたの問題でした。解決策は、リストが実際にはシリアライズ可能なタイプであるため、あなたが自分で言及したことです。

コード生成yield return new KeyValuePair<??? ???>(???,???);

   [CompilerGenerated, DebuggerDisplay(@"\{ x = {x}, y = {y} }", Type="<Anonymous Type>")]
internal sealed class <>f__AnonymousType0<<x>j__TPar, <y>j__TPar>
{
    // Fields
    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    private readonly <x>j__TPar <x>i__Field;
    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    private readonly <y>j__TPar <y>i__Field;

    // Methods
    [DebuggerHidden]
    public <>f__AnonymousType0(<x>j__TPar x, <y>j__TPar y)
    {
        this.<x>i__Field = x;
        this.<y>i__Field = y;
    }

    [DebuggerHidden]
    public override bool Equals(object value)
    {
        var type = value as <>f__AnonymousType0<<x>j__TPar, <y>j__TPar>;
        return (((type != null) && EqualityComparer<<x>j__TPar>.Default.Equals(this.<x>i__Field, type.<x>i__Field)) && EqualityComparer<<y>j__TPar>.Default.Equals(this.<y>i__Field, type.<y>i__Field));
    }

    [DebuggerHidden]
    public override int GetHashCode()
    {
        int num = -576933007;
        num = (-1521134295 * num) + EqualityComparer<<x>j__TPar>.Default.GetHashCode(this.<x>i__Field);
        return ((-1521134295 * num) + EqualityComparer<<y>j__TPar>.Default.GetHashCode(this.<y>i__Field));
    }

    [DebuggerHidden]
    public override string ToString()
    {
        StringBuilder builder = new StringBuilder();
        builder.Append("{ x = ");
        builder.Append(this.<x>i__Field);
        builder.Append(", y = ");
        builder.Append(this.<y>i__Field);
        builder.Append(" }");
        return builder.ToString();
    }

    // Properties
    public <x>j__TPar x
    {
        get
        {
            return this.<x>i__Field;
        }
    }

    public <y>j__TPar y
    {
        get
        {
            return this.<y>i__Field;
        }
    }
}
于 2010-12-04T09:56:11.627 に答える
3

これは最も巧妙な方法ではないため、より良い方法を見つけることができれば幸いですが、コンパイラによって生成されたコードを忘れて、実装する独自のクラスを作成することもできますIEnumerator<MyItem>(IEnumerable<MyItem>複雑さによっては、実装する独自のクラスを作成することもできます)。物事を簡単にしたり難しくしたりする可能性があります)、.NET2.0 より前の時代とほぼ同じように、列挙子を構築します。

実際のイテレータ ブロックのロジックが非常に複雑な場合は、コンパイラが作成したクラスのリフレクションを調べると、これを行うのに適した出発点になる場合がありますが、生成されたコードがより複雑になる場合があります (少なくとも、よりも読みにくい)。

IEnumeratorクラスを構築しなければならないのは、99% の確率で非常にうまくいっているのに、いつも少しがっかりしますがyield、それでも必要な場合があり、ここで問題を解決できる可能性があります。

于 2010-11-30T11:26:55.910 に答える
0

この問題に投票できます: https://connect.microsoft.com/VisualStudio/feedback/details/667328/yield-and-securitycriticalattribute-problem

[編集] Microsoft からの応答:

私たちは SecurityCritical イテレータを検討し、少なくともこのリリースでは機能させようとしないことにしました。これは重要で複雑な作業であり、IEnumerator.MoveNext を介した呼び出しは重要ではないインターフェイスを介した呼び出しになるため、あまり有用ではないようです。

これについては、今後のリリースで再検討する予定です。特に、その一般的なシナリオが見られる場合。

于 2011-05-10T09:34:29.813 に答える