开发者

Problem using C# iterator methods with code access security

I have a simple method that uses an iterator block to return an IEnumerable<T>:

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

Ordinarily, this method works fine, but if I apply a [Securit开发者_Go百科yCritical] attribute to the assembly (or to the class that contains the above method), it throws a TypeLoadException when attempting to invoke the method. The type that is failing to load is the compiler-generated class that corresponds to the iterator method, and it is its GetEnumerator method that is causing the problem, since it is security transparent.

For comparison, if I modify the above method so that it populates and returns a List<MyItem>, everything works fine.

Any suggestions?

Thanks,

Tim.


It isn't the neatest thing to do, so hopefully you can find a better way, but you could always forgo the compiler-generated code and create your own class that implements IEnumerator<MyItem> (and perhaps your own class implementing IEnumerable<MyItem> - depending on complexity, doing so may make things easier or more difficult), and then build the enumerator more or less as you would in the days before .NET2.0.

If the logic of your real iterator block is very complicated, you might find looking at the reflection of the class the compiler created for you to be a good starting point in doing this, though sometimes the generated code is more complicated (or at least, less readable) than the approach one would take oneself.

It's always a bit disappointing to have to build an IEnumerator class when yield has made it so nice for us 99% of the time, but there are still times when its necessary, and it might solve your problem here.


I had the very same problem, in a complicated application. Spring comes in between and said that the 'blahblah' type is not Serializable and sure it was correct, Here is the disassembled code of compiler generated code and sure it's not Serializable. Maybe this was your problem too, and the solution is what you mentioned yourself cause the List is actually a Serializable type.

The code generate for 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;
        }
    }
}


You can vote for this issue: https://connect.microsoft.com/VisualStudio/feedback/details/667328/yield-and-securitycriticalattribute-problem

[EDIT] Response from Microsoft:

We've looked at SecurityCritical iterators and decided not to try to make that work at least for this release. It is a significant and complicated effort, and it does not seem too useful, as the call through IEnumerator.MoveNext would be calling through a non-critical interface.

We'll probably revisit this again in a later release; especially if we see common scenarios for it.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜