tags:

views:

192

answers:

3

Hi,

I need to simulate in C# code (with ilGenerator.Emit) the following function

public void AssignAttribute(ref ValueHolder output, Assignment assignment) {
    ResultAttribute attribute = null;

    if ( (attribute = output.MultipleResults.Find(delegate(ResultAttribute o) {
        return o.Name == assignment.Name;
    })) != null)
        attribute.Value = assignment.Value;
    }

Can anybody help me, plz?

Paul

+7  A: 

The thing to do is to compile the method in a project C#, then have a look at the IL in the assembly it generates using Reflector. You can easily replicate that IL using Emit and make whatever dynamic changes you need.

thecoop
Jonathan de Halleux has written a Reflection.Emit language add-in (http://reflectoraddins.codeplex.com/Wiki/View.aspx?title=ReflectionEmitLanguage) for Reflector that makes this kind of thing even easier. It's not quite perfect, but it'll generally get you about 95% of the way there, which is a heck of a lot better than starting with pure IL...
Nicole Calinoiu
A: 

Thanks for your reply, everything perfect until now. I get the following code:

.method public hidebysig instance void  AssignAttribute(class V24.Generated.ValueHolder& output,
                                                        class [nviss]NViss.Assignment assignment) cil managed
{
  // Code size       68 (0x44)
  .maxstack  4
  .locals init ([0] class [V24.Util]V24.Util.ResultAttribute attribute,
           [1] class V24.Generated.Worker/'<>c__DisplayClass1' '<>8__locals2',
           [2] bool CS$4$0000)
  IL_0000:  newobj     instance void V24.Generated.Worker/'<>c__DisplayClass1'::.ctor()
  IL_0005:  stloc.1
  IL_0006:  ldloc.1
  IL_0007:  ldarg.2
  IL_0008:  stfld      class [nviss]NViss.Assignment V24.Generated.Worker/'<>c__DisplayClass1'::assignment
  IL_000d:  nop
  IL_000e:  ldnull
  IL_000f:  stloc.0
  IL_0010:  ldarg.1
  IL_0011:  ldind.ref
  IL_0012:  ldfld      class [mscorlib]System.Collections.Generic.List`1<class [V24.Util]V24.Util.ResultAttribute> V24.Generated.ValueHolder::F_WebS_Beitrag
  IL_0017:  ldloc.1
  IL_0018:  ldftn      instance bool V24.Generated.Worker/'<>c__DisplayClass1'::'<AssignAttribute>b__0'(class [V24.Util]V24.Util.ResultAttribute)
  IL_001e:  newobj     instance void class [mscorlib]System.Predicate`1<class [V24.Util]V24.Util.ResultAttribute>::.ctor(object,
                                                                                                                         native int)
  IL_0023:  callvirt   instance !0 class [mscorlib]System.Collections.Generic.List`1<class [V24.Util]V24.Util.ResultAttribute>::Find(class [mscorlib]System.Predicate`1<!0>)
  IL_0028:  dup
  IL_0029:  stloc.0
  IL_002a:  ldnull
  IL_002b:  ceq
  IL_002d:  stloc.2
  IL_002e:  ldloc.2
  IL_002f:  brtrue.s   IL_0042
  IL_0031:  ldloc.0
  IL_0032:  ldloc.1
  IL_0033:  ldfld      class [nviss]NViss.Assignment V24.Generated.Worker/'<>c__DisplayClass1'::assignment
  IL_0038:  callvirt   instance string [nviss]NViss.NamedElement::get_Value()
  IL_003d:  stfld      string [V24.Util]V24.Util.SKFZAttribute::Value
  IL_0042:  nop
  IL_0043:  ret
} // end of method Worker::AssignAttribute

I cand easily replicate this IL using Emit, except with

  IL_0018:  ldftn      instance bool V24.Generated.Worker/'<>c__DisplayClass1'::'<AssignAttribute>b__0'(class [V24.Util]V24.Util.ResultAttribute)
  IL_001e:  newobj     instance void class [mscorlib]System.Predicate`1<class [V24.Util]V24.Util.ResultAttribute>::.ctor(object,
                                                                                                                         native int)
  IL_0023:  callvirt   instance !0 class [mscorlib]System.Collections.Generic.List`1<class [V24.Util]V24.Util.ResultAttribute>::Find(class [mscorlib]System.Predicate`1<!0>)

Can you help me plz to replicate this with IL?

+1  A: 

c# create a closure (see wikipedia if you not familiar with) for you since in the anonymous method body you reference to the assignment variable (which is parameter in your case but this doesn't matter).

You need to create class holder for anonymous delegate (at least c# compiler does this)

then you need to create field in this class since your delegate closeover (i'm not native english so here maybe misspelling ) Assignment assignment parameter

Then in the body of AssignAttribute you should emit class instaniation IL_0000: newobj instance void V24.Generated.Worker/'<>c__DisplayClass1'::.ctor()

as well as feild assignment IL_0008: stfld class [nviss]NViss.Assignment V24.Generated.Worker/'<>c__DisplayClass1'::assignment

note that since filed initialization finished anywhere access to local variable was replaced with access to field

once again sorry for my English

Trickster