0

The problem

I need to generate a fast reflection based method during runtime. Therefore i looked into dynamic methods. The problem is im stuck with my limited knowledge.

Thats the method i need to call with a dynamic method.


public struct EntityManager{

    public void SetComponent<T>(Entity e, T component) where T : struct, IComponentData{
       // Simplified
    }
}

// The component to pass in it
public struct ComponentExample : IComponentData{}

And im stuck with the part where i need to pass the Entity and the Component into the method. I just cant find any example on how we do that.

var dm = new DynamicMethod(
    "SetComponent",       
    typeof(void),  
    new [] { typeof(Entity), typeof(ComponentExample)}, 
    false
);             

var il = dm.GetILGenerator();
// Emit Entity & the ComponentExample ???
il.EmitCall(OpCodes.Call, genericMethod, null);
il.Emit(OpCodes.Ret);

The question

How exactly do we "emit" an struct ( Entity ) and an object into the DynamicMethod for executing it ? Glad for any help on this topic !

6
  • What are you actually trying to do? You don't say what the dynamic method is for, and I suspect there are far easier ways of accomplishing the same thing, such as reflection and delegate caching. If you really want to go down the road of handcoding MSIL, you need to read up ECMA-335, in particular Part IV Commented Mar 30, 2021 at 22:31
  • @Charlieface Understandable... I didnt want to go into detail. But i need to invoke that method with dynamic methods. i cant use normal reflection because of the garbage such a call produces. Commented Mar 30, 2021 at 22:47
  • 1
    I would venture to say that dynamic methods produce far more garbage: they actually produce a whole temporary assembly. As I said, if you can explain your use case, perhaps we can do this much simpler: delegate caching is exceedingly fast. Not clear anyway why you need dynamic here as you know the types. Perhaps also explain what you mean "emit" an struct ( Entity ) and an object into the DynamicMethod can we have some pseudo-code as to what it is supposed to do: is it just passing empty objects and structs with the default constructors, or do you have specific constructors you need to call? Commented Mar 30, 2021 at 22:52
  • 1
    Looking at your code again: ldarg.0, ldarg.1 is probably all you need if those types are parameters. But if you know the types that you need for the generic method, why can you not call it directly? Can you elaborate more on where you get the type parameters, I think there is a much better method Commented Mar 30, 2021 at 23:02
  • 2
    I don't see how Dynamic will help you, ultimately at some point you have to call the DynamicMethod with reflection also. Please edit your question and add more detail as to how you get this object and store it (is it an object variable?), how you intend to pass it to the DynamicMethod, bearing in mind you don't know the type? Or is the DM not itself generic, in which case we are back to square one? I just don't understand how you are passing this object around? Commented Mar 30, 2021 at 23:55

1 Answer 1

1

Does it have to be dynamic, or would reflection be enough?

typeof(EntityManager)
    .GetMethod(nameof(EntityManager.SetComponent))
    .MakeGenericMethod(typeof(ComponentExample))
    .Invoke(entityManager, new object[] { component });
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks ! I was already using this before i decided to go with dynamic methods ^^ the problem is... It produces insane amounts of allocs if called recently. Even if the methodinfo is cached. So... It would be great if you could provide an example with dynamic methods.
I think the allocs are caused not by how the method is being invoked, but by boxing the struct as an object. Where is this component data coming from? You need to know the type when you get it, as well as when you set it. If you can wrap both the get and the set methods in a generic function, then you should be able to invoke that without causing the component to be boxed
Thanks for the reply ! Well i profiled it lately. The boxing happens before the method.invoke call. Wayyyy before. My profiler told me that the gc allocs arw caused my a generic check inside the .invoke call EACH time its invoked :/

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.