How can we help you today? How can we help you today?

disassembled Source code can be read for anonymouse type?

I use NET reflector to disassemble a code for WPF as blow:

this.ExpandStoryboard = (VisualStateManager.GetVisualStateGroups(child) as Collection<VisualStateGroup>).Where<VisualStateGroup>(delegate (VisualStateGroup stategroup) {
return (stategroup.Name == "PopupStates");
}).SelectMany(delegate (VisualStateGroup stategroup) {
return (stategroup.States as Collection<VisualState>);
}, delegate (VisualStateGroup stategroup, VisualState state) {
return new { stategroup = stategroup, state = state };
}).Where(delegate (<>f__AnonymousType0<VisualStateGroup, VisualState> <>h__TransparentIdentifier3) {
return (<>h__TransparentIdentifier3.state.Name == "PopupOpened");
}).Select(delegate (<>f__AnonymousType0<VisualStateGroup, VisualState> <>h__TransparentIdentifier3) {
return <>h__TransparentIdentifier3.state.Storyboard;
}).FirstOrDefault<Storyboard>();

but got error with following parts:
delegate (<>f__AnonymousType0<VisualStateGroup, VisualState> <>h__TransparentIdentifier3) {
return (<>h__TransparentIdentifier3.state.Name == "PopupOpened");
}).Select(delegate (<>f__AnonymousType0<VisualStateGroup, VisualState> <>h__TransparentIdentifier3) {
return <>h__TransparentIdentifier3.state.Storyboard;

what is the right code for above disassemble code?
kentzhou
0

Comments

14 comments

  • Clive Tong
    The types named like "<>f__AnonymousType0" are the anonymous types that the compiler generates for code such as the following

    int[] items = new int[] { 1, 2, 3, 4 };
    var result = items.Select(x => new { A = x });

    where it needs to generate a class with a property A for holding the result of the select.

    If I compile the above code and de-compile using Reflector, with the View/Options/Optimization set to 3.5 I get

    int[] items = new int[] { 1, 2, 3, 4 };
    var result = from x in items select new { A = x };

    but if I set it to 1.0, Reflector no longer tries to get rid of the anonymous types and I see

    var result = new int[] { 1, 2, 3, 4 }.Select((CS$<>9__CachedAnonymousMethodDelegate1 != null) ? CS$<>9__CachedAnonymousMethodDelegate1 : (CS$<>9__CachedAnonymousMethodDelegate1 = new Func<int, <>f__AnonymousType0<int>>(MainWindow.<Test>b__0)));
    }

    If you have the optimization level set to 3.5, then it is a bug if Reflector is not getting rid of the anonymous types. Do you have a reproducible example we can have a look at to debug this?

    In your example, the new { stategroup = stategroup, state = state } is the type the compiler is generating as <>f__AnonymousType0 - this instance is then being passed into the Where and the StoryBoard is being pulled out of the state component and returned.
    Clive Tong
    0
  • kentzhou
    Here is an example:

    bool istrue = (CS$<>9__CachedAnonymousMethodDelegate8 == null) && Enumerable.All<FrameworkElement>(allParents, CS$<>9__CachedAnonymousMethodDelegate8);

    [CompilerGenerated]
    private static Func<FrameworkElement, bool> CS$<>9__CachedAnonymousMethodDelegate8;

    what's the possible original code with lambda expression for above disassembled code?
    kentzhou
    0
  • Porter321
    Thanks for you information i newly join and your post help me.
    Porter321
    0
  • slaneyrw
    Somewhere in the updates from version 5.x to 6.x ( I suspect when .NET 4.0 support was added ) the generation of C# for linq, initializers, extensions and anonymous methods has become atrocious.

    It is almost making the tool useless as C# language features in our codebase become common place.

    For example generator is now displaying direct execution of the static methods instead as an extension.

    ie

    Real Code
    private class ReflectorExample
    &#123;
        public ReflectorExample&#40;&#41;
        &#123;
            List&lt;string&gt; aListOfStrings = new List&lt; string &gt;&#40;&#41; &#123; "One", "Two", "Three" &#125;;
    
            int countOf = aListOfStrings.Where&#40; item =&gt; item.Length == 3 &#41;.Count&#40;&#41;;
        &#125;
    &#125;
    

    Reflected code
    private class ReflectorExample
    &#123;
        &#91;CompilerGenerated&#93;
        private static Func&lt;string, bool&gt; CS$&lt;&gt;9__CachedAnonymousMethodDelegate4;
    
        &#91;CompilerGenerated&#93;
        private static bool &lt;.ctor&gt;b__3&#40;string item&#41;
        &#123;
            return &#40;item.Length == 3&#41;;
        &#125;
    
        // Methods
        public ReflectorExample&#40;&#41;
        &#123;
            List&lt;string&gt; &lt;&gt;g__initLocal2 = new List&lt;string&gt;&#40;&#41;;
            &lt;&gt;g__initLocal2.Add&#40;"One"&#41;;
            &lt;&gt;g__initLocal2.Add&#40;"Two"&#41;;
            &lt;&gt;g__initLocal2.Add&#40;"Three"&#41;;
            List&lt;string&gt; aListOfStrings = &lt;&gt;g__initLocal2;
            if &#40;CS$&lt;&gt;9__CachedAnonymousMethodDelegate4 == null&#41;
            &#123;
                CS$&lt;&gt;9__CachedAnonymousMethodDelegate4 = new Func&lt;string, bool&gt;&#40;null, &#40;IntPtr&#41; &lt;.ctor&gt;b__3&#41;;
            &#125;
            int countOf = Enumerable.Where&lt;string&gt;&#40;aListOfStrings, CS$&lt;&gt;9__CachedAnonymousMethodDelegate4&#41;.Count&lt;string&gt;&#40;&#41;;
        &#125;
    &#125;
    
    slaneyrw
    0
  • Clive Tong
    Hi.

    Could you send me a self-contained example of the failure to decompile? As far as I know, that support for .net 4 should not have changed anything in this area.

    If I take the code you gave and compile it, I see
        public ReflectorExample&#40;&#41;
        &#123;
            List&lt;string&gt; list = new List&lt;string&gt; &#123; "One", "Two", "Three" &#125;;
            &#40;from item in list
                where item.Length == 3
                select item&#41;.Count&lt;string&gt;&#40;&#41;;
        &#125;
    

    unless I have the optimisation level (View/Options/Optimization) set to less than 3.5.
    Clive Tong
    0
  • slaneyrw
    Code code above is compiled in VS2008 using .NET 3.5

    I see no difference using any optimization settings from 2.0 through to 4.0

    My reflector version is 6.5.0.135.

    What you posted is what I used to see when I selected .NET 3.5 optimization, but I prefer the method syntax so I set my optimization to 2.0.

    Somewhere in the upgrade path from 5.x it changed.
    slaneyrw
    0
  • Clive Tong
    I can now reproduce what you're seeing.

    It happens if the 3.5 application is decompiled in a situation where the 4.0 version of System.Core is included in the assembly set. I imagine you have an assembly list set up for .NET 4 and have opened the 3.5 assembly in that set.

    I didn't see it because I had System.Core 3.5 selected in my loaded assemblies since I was using a 3.5 framework set of assemblies in my assembly list.

    I'll look into it. The workaround is to set up a .NET 3.5 assembly list, using say, File/Open List, Add, Framework35, double-click framework 35, select the 3.5 framework. Opening the assembly within this group of pre-loaded assemblies should give you the behaviour you are looking for.
    Clive Tong
    0
  • slaneyrw
    Thanks Clive...

    I reset my list to Framework 3.5 and I now see the correct syntax.

    Now if only I could see the code using Method syntax instead of Linq, like the original code, everything would be perfect 8)
    slaneyrw
    0
  • Clive Tong
    Using View/Options to turn the optimization down to .NET2 gives something pretty close to the original.
       int num = source.Where&lt;string&gt;&#40;delegate &#40;string item&#41; &#123;
                return &#40;item.Length == 3&#41;;
            &#125;&#41;.Count&lt;string&gt;&#40;&#41;;
    
    Clive Tong
    0
  • lukit
    Hi

    It looks like I have (almost) the same problem, but I can't solve it. Reflector version: 6.5.0.135.
    The workaround is to set up a .NET 3.5 assembly list, using say, File/Open List, Add, Framework35, double-click framework 35, select the 3.5 framework. Opening the assembly within this group of pre-loaded assemblies should give you the behaviour you are looking for.

    Done.

    Original code:
    using System;
    using System.Collections;
    
    namespace Crh.GbSheets
    &#123;
    	public class GbsElems : IEnumerable
    	&#123;
    		private ArrayList items;
    
    		public GbsElems&#40;&#41;
    		&#123;
    			items = new ArrayList&#40;&#41;;
    		&#125;
    
    		public IEnumerator GetEnumerator&#40;&#41;
    		&#123;
    			return items.GetEnumerator&#40;&#41;;
    		&#125;
    
    		public IEnumerable Reverse
    		&#123;
    			get
    			&#123;
    				for &#40;int i = items.Count - 1; i &gt;= 0; i--&#41;
    					yield return items&#91;i&#93;;
    			&#125;
    		&#125;
    	&#125;
    &#125;
    

    Reflectored code:
        public IEnumerable Reverse
        &#123;
            get
            &#123;
                return new &lt;get_Reverse&gt;d__0&#40;-2&#41; &#123; &lt;&gt;4__this = this &#125;;
            &#125;
        &#125;
    
        // Nested Types
        &#91;CompilerGenerated&#93;
        private sealed class &lt;get_Reverse&gt;d__0 : IEnumerable&lt;object&gt;, IEnumerable, IEnumerator&lt;object&gt;, IEnumerator, IDisposable
        &#123;
    ...
    

    Optimization in option is set to .NET 3.5, but using 2.0 is (almost) the same.

    My main problem is the reflectored code does not compile. Is it possible to get something compileable?

    Thank you very much,
    Gyula
    lukit
    0
  • lukit
    Naming convention of temp variables does not make sense to the compiler also:
    internal static double ConvertToDouble&#40; object o &#41;
    		&#123;
    			if &#40;o is DateTime&#41;
    			&#123;
    				return &#40;double&#41;&#40;&#40;&#40;DateTime&#41;o&#41;.Ticks&#41;;
    			&#125;
    
    			else if &#40;o is IConvertible&#41;
    			&#123;
    				return System.Convert.ToDouble&#40;o&#41;;
    			&#125;
    
    			throw new System.Exception&#40; "Invalid datatype" &#41;;
    		&#125;
    

    becomes:
    internal static double ConvertToDouble&#40;object o&#41;
    &#123;
        if &#40;o is DateTime&#41;
        &#123;
            DateTime CS$0$0002 = &#40;DateTime&#41; o;
            return &#40;double&#41; CS$0$0002.Ticks;
        &#125;
        if &#40;!&#40;o is IConvertible&#41;&#41;
        &#123;
            throw new Exception&#40;"Invalid datatype"&#41;;
        &#125;
        return Convert.ToDouble&#40;o&#41;;
    &#125;
    

    Any idea on this one?
    lukit
    0
  • Clive Tong
    Hi.

    In the first example, the code is defining an Enumerable using the yield form. The C# compiler code generates this by defining an anonymous class which implements a state machine that generates the items. Currently, Reflector does not decompile this state machine back into code that uses the yield statement.

    In the second example, the CS$0$0002 is a temporary variable that the C# compiler has generated. These symbols are present in a pdb file associated with the assembly. Reflector will use the names from the pdb file if it can find it, but only if the option View/Options/Disassembler/Show PDB symbols is checked. Unchecking the option will get rid of the variable.
    Clive Tong
    0
  • lukit
    Thank you very much for the support!
    Clive Tong wrote:
    Currently, Reflector does not decompile this state machine back into code that uses the yield statement.

    Is it possible to get a code from Reflector which compiles?
    lukit
    0
  • Clive Tong
    No. You'll have to hand edit it to get it to compile.
    Clive Tong
    0

Add comment

Please sign in to leave a comment.