Rettoph
Rettoph
CC#
Created by Rettoph on 9/24/2024 in #help
Generically creating a delegate from a MethodInfo with parameter upcasting
I have been pursuing a possible solution by creating a DynamicMethod - the proof of concept i have at the moment looks like so:
class DelegateHelper
{
public static TDelegate CreateDelegateWithCasting<TDelegate>(MethodInfo method)
where TDelegate : Delegate
{
MethodInfo outDelegateSignature = typeof(TDelegate).GetMethod("Invoke") ?? throw new NotImplementedException();

DynamicMethod dynamicMethod = new DynamicMethod(
"Test",
typeof(void),
outDelegateSignature.GetParameters().Select(x => x.ParameterType).ToArray(),
typeof(Program).Module);

ILGenerator ilGenerator = dynamicMethod.GetILGenerator();

// Load arguments
ilGenerator.Emit(OpCodes.Ldarg_0);
ilGenerator.Emit(OpCodes.Box, outDelegateSignature.GetParameters().First().ParameterType);

ilGenerator.Emit(OpCodes.Call, method);
ilGenerator.Emit(OpCodes.Ret);

return dynamicMethod.CreateDelegate<TDelegate>();
}
}
class DelegateHelper
{
public static TDelegate CreateDelegateWithCasting<TDelegate>(MethodInfo method)
where TDelegate : Delegate
{
MethodInfo outDelegateSignature = typeof(TDelegate).GetMethod("Invoke") ?? throw new NotImplementedException();

DynamicMethod dynamicMethod = new DynamicMethod(
"Test",
typeof(void),
outDelegateSignature.GetParameters().Select(x => x.ParameterType).ToArray(),
typeof(Program).Module);

ILGenerator ilGenerator = dynamicMethod.GetILGenerator();

// Load arguments
ilGenerator.Emit(OpCodes.Ldarg_0);
ilGenerator.Emit(OpCodes.Box, outDelegateSignature.GetParameters().First().ParameterType);

ilGenerator.Emit(OpCodes.Call, method);
ilGenerator.Emit(OpCodes.Ret);

return dynamicMethod.CreateDelegate<TDelegate>();
}
}
But... im already starting to see how much work its going to take to achieve my goal. Is this already a solved problem? I feel like i cant be the first to want this - is there a better solution than the IL & reflection madness ive embarked on? Perhaps a usefil library that already did the hard work for me? Any ideas would be hugely appreciated. thanks!
2 replies
CC#
Created by Mazranel on 8/2/2024 in #help
Implementing scripting in a game engine
ive not worked with either enough to have an informed opinion. I did like working with mmoonsharp though
41 replies
CC#
Created by Mazranel on 8/2/2024 in #help
Implementing scripting in a game engine
ive not used it a ton, but Moonsharp might be a good option https://github.com/moonsharp-devs/moonsharp
41 replies
CC#
Created by Rhys on 4/22/2024 in #help
Discord.net help - Trying to access a users roles
No promises, but sure.
84 replies
CC#
Created by Rhys on 4/22/2024 in #help
Discord.net help - Trying to access a users roles
do you have the code sitting anywhere public? I can try taking a quick stab at it locally
84 replies
CC#
Created by Rhys on 4/22/2024 in #help
Discord.net help - Trying to access a users roles
No description
84 replies
CC#
Created by Rettoph on 11/30/2023 in #help
Contravariant Help
Sorry for the lack of response, The same result happens regardless of the type parameter used. I found a work around for my personal use case so marking this as closed.
8 replies
CC#
Created by Rettoph on 11/30/2023 in #help
Contravariant Help
c#
MySubscriber subscriber = new MySubscriber();

Action<MessageC> process = typeof(MySubscriber)
.GetInterfaceMap(typeof(ISubscriber<MessageB>))
.InterfaceMethods[0]
.CreateDelegate<Action<MessageC>>(subscriber);

process(new MessageC()); // Output: "Processing MessageA"
c#
MySubscriber subscriber = new MySubscriber();

Action<MessageC> process = typeof(MySubscriber)
.GetInterfaceMap(typeof(ISubscriber<MessageB>))
.InterfaceMethods[0]
.CreateDelegate<Action<MessageC>>(subscriber);

process(new MessageC()); // Output: "Processing MessageA"
8 replies
CC#
Created by Rettoph on 11/30/2023 in #help
Contravariant Help
After asking around on the MonoGame server one thing ive found is that my question probably wasnt very clear My question is about contravariance at its core. Given the code above, the following is valid:
c#
ISubscriber<MessageC> subscriber = new MySubscriber();
subscriber.Process(new MessageC()); // Currently outputs: "Processing MessageA"
c#
ISubscriber<MessageC> subscriber = new MySubscriber();
subscriber.Process(new MessageC()); // Currently outputs: "Processing MessageA"
As MySubscriber implements both ISubscriber<MessageA> and ISubscriber<MessageB>, and the ISubscriber interfaces utilizes the in keyword i can cast MySubscriber directly to ISubscriber<MessageC>. The issue is i want to be able to invoke all ISubscriber implementations that can be casted to ISubscriber<MessageC>. Doing ((ISubscriber<MessageC>)new MySubscriber()).Process() is valid, but only gives me the first one. Its an issue because ISubscriber<MessageC> is ambiguous, there are two interfaces that can meet that criteria. Even with reflection i cant seem to find a way to invoke the ISubscriber<MessageB> implementation
8 replies
CC#
Created by Rettoph on 11/30/2023 in #help
Contravariant Help
The end goal being
c#
MySubscriber subscriber = new MySubscriber();
ISubscriber<MessageC>[] c_subscribers = subscriber.GetAllApplicableSubscribers<MessageC>();
MessageC message = new MessageC();
foreach(ISubscriber<MessageC> c_subscriber in c_subscribers)
{
c_subscriber.Process(message);
}
c#
MySubscriber subscriber = new MySubscriber();
ISubscriber<MessageC>[] c_subscribers = subscriber.GetAllApplicableSubscribers<MessageC>();
MessageC message = new MessageC();
foreach(ISubscriber<MessageC> c_subscriber in c_subscribers)
{
c_subscriber.Process(message);
}
with an output of
Processing MessageA
Processing MessageB
Processing MessageA
Processing MessageB
8 replies