add delegates and call MulticastDelegate by reflection - c#

I have the following scenario
I have a loop which has an Update callback which several objects use CreateDelegate to creat their own delegates and add themselves to it at runtime.
now I want to avoid creating N delegates for N objects so I thought using a multi cast open delegate I can create one delegate
add all instances to it and call it,
How can I do it via reflection
I create the delegate using CreateDelegate from my method info once and then call NewMultiCastDelegate via reflection and send it the list of objects but things go wron when I call invoke with another dummy instance to call it, unprotected memory violation exception is thrown.
How can I do it?
I can not do it without reflection since my objects methods will be known at runtime and anyone with an Update method should be called by this loop manager.
This is for a game engine

UPDATE:
There are two issues with using MulticastDelegate + open instance delegates.
It's not possible to invoke open instance delegates with multiple unrelated types. Take types A and B, each with an Update method. An open instance delegate of A.Update can be invoked with instances of A (or types derived from A), but not with instances of B. That's because A.Update and B.Update are unrelated as far as the .NET runtime is concerned.
Multiple open instance delegates can be combined in a single MulticastDelegate, but this doesn't fit your use case. You want to call the Update method on each instance in a list. Invoking a MulticastDelegate will sequentially call each delegate in its invocation list with the same parameter list. So a MulticastDelegate with multiple open instance delegates could be used to invoke a list of methods on a single instance, but not a single method on a list of instances. Does that make sense?
I assume you're trying to speed up adding a Unity Component to your engine emulator, and that's why you want to stop calling CreateDelegate for each one.
Instead of using a MulticastDelegate, you can achieve a speedup by creating open instance delegates the first time a type is added, then caching those delegates for reuse.
Here's some code along those lines:
public class ComponentEventAggregator
{
public void AddComponent(object component)
{
var typeGroup = this.GetTypeGroup(component.GetType());
typeGroup.AddComponent(component);
}
public void Update()
{
foreach (var typeGroup in this.typeGroupsByType.Values)
{
typeGroup.Update();
}
}
public void RemoveComponent(object component)
{
TypeGroup typeGroup;
if (this.typeGroupsByType.TryGetValue(component.GetType(), out typeGroup))
{
typeGroup.RemoveComponent(component);
}
}
private TypeGroup GetTypeGroup(Type type)
{
TypeGroup typeGroup;
if (!this.typeGroupsByType.TryGetValue(type, out typeGroup))
{
typeGroup = TypeGroup.Create(type);
this.typeGroupsByType[type] = typeGroup;
}
return typeGroup;
}
private abstract class TypeGroup
{
public abstract void Update();
// ... LateUpdate, OnApplicationPause, etc.
public abstract void AddComponent(object component);
public abstract void RemoveComponent(object component);
// Create a TypeGroup<T> for the specified type
public static TypeGroup Create(Type type)
{
var closedDelegatesType = typeof(TypeGroup<>).MakeGenericType(new[] { type });
var typeDelegates = closedDelegatesType.GetConstructor(Type.EmptyTypes).Invoke(new object[0]);
return (TypeGroup)typeDelegates;
}
}
private class TypeGroup<T> : TypeGroup where T : class
{
public TypeGroup()
{
this.update = CreateOpenDelegate("Update");
this.lateUpdate = CreateOpenDelegate("LateUpdate");
this.onApplicationPause = CreateOpenDelegate<bool>("OnApplicationPause");
// ...other Unity events
}
public override void Update()
{
if (this.update != null)
{
foreach (var component in this.components)
{
this.update(component);
}
}
}
public override void AddComponent(object component)
{
var t = component as T;
if (t != null)
{
this.components.Add(t);
}
}
public override void RemoveComponent(object component)
{
var t = component as T;
if (t != null)
{
this.components.Remove(t);
}
}
private static Action<T> CreateOpenDelegate(string functionName)
{
var method = GetMethod(functionName, Type.EmptyTypes);
if (method == null)
{
return null;
}
return (Action<T>)Delegate.CreateDelegate(typeof(Action<T>), method);
}
private static Action<T, TArg1> CreateOpenDelegate<TArg1>(string functionName)
{
var method = GetMethod(functionName, new[] { typeof(TArg1) });
if (method == null)
{
return null;
}
return (Action<T, TArg1>)Delegate.CreateDelegate(typeof(Action<T, TArg1>), method);
}
private static MethodInfo GetMethod(string functionName, Type[] parameterTypes)
{
return typeT.GetMethod(functionName, BindingFlags.Instance | BindingFlags.Public, null, parameterTypes, null);
}
private readonly Action<T> update;
private readonly Action<T> lateUpdate;
private readonly Action<T, bool> onApplicationPause;
private List<T> components = new List<T>();
private static readonly Type typeT = typeof(T);
}
private Dictionary<Type, TypeGroup> typeGroupsByType = new Dictionary<Type, TypeGroup>();
}
This gives a 50X speedup to add a Component compared to Delegate.CreateDelegate on my PC.
Test times with 1 million A and 1 million B instances:
10892ms add closed delegates with CreateDelegate for all Components
11ms Update via the closed delegates
187ms add all Components to the type-based aggregator
30ms Update via the open instance delegates (i.e. Update on aggregator)
The Update method in both A and B increments a private static int.
ORIGINAL:
It sounds like you would be better off exposing a C# event on your loop manager and adding subscriptions that call the Update methods. Alternately all the types with the Update method could implement an IUpdater interface, then you'd send a list of IUpdater instances to the loop manager instead of a list of objects.
Assuming you really do have some other good reason for using reflection...
class Program
{
public class Updater
{
public void AddUpdateListeners(object[] listeners)
{
Func<object, MethodInfo> getUpdateMethod = l =>
l.GetType()
.GetMethod("Update", BindingFlags.Instance | BindingFlags.Public, null, new Type[0], null);
listeners
.Select(listener => new { listener, update = getUpdateMethod(listener) })
.Where(l => l.update != null)
.Select(l => Delegate.CreateDelegate(typeof(UpdateDelegate), l.listener, l.update))
.OfType<UpdateDelegate>()
.ToList()
.ForEach(d => this.updateDel += d);
}
public void PublishCallbacks()
{
var handler = this.updateDel;
if (handler != null)
{
handler();
}
}
private delegate void UpdateDelegate();
private UpdateDelegate updateDel;
}
static void Main(string[] args)
{
var updater = new Updater();
updater.AddUpdateListeners(new object[] { new A(), new B(), });
updater.PublishCallbacks();
}
public class A
{
public void Update()
{
Console.WriteLine("A updated");
}
}
public class B
{
public void Update()
{
Console.WriteLine("B updated");
}
}
}

Related

Access static class of dynamic (not known at compile time) type? [duplicate]

I have several static classes in the namespace mySolution.Macros such as
static class Indent{
public static void Run(){
// implementation
}
// other helper methods
}
So my question is how it will be possible to call those methods with the help of reflection?
If the methods where NOT to be static then I could do something like:
var macroClasses = Assembly.GetExecutingAssembly().GetTypes().Where( x => x.Namespace.ToUpper().Contains("MACRO") );
foreach (var tempClass in macroClasses)
{
var curInsance = Activator.CreateInstance(tempClass);
// I know have an instance of a macro and will be able to run it
// using reflection I will be able to run the method as:
curInsance.GetType().GetMethod("Run").Invoke(curInsance, null);
}
I will like to keep my classes static. How will I be able to do something similar with static methods?
In short I will like to call all the Run methods from all the static classes that are in the namespace mySolution.Macros.
As the documentation for MethodInfo.Invoke states, the first argument is ignored for static methods so you can just pass null.
foreach (var tempClass in macroClasses)
{
// using reflection I will be able to run the method as:
tempClass.GetMethod("Run").Invoke(null, null);
}
As the comment points out, you may want to ensure the method is static when calling GetMethod:
tempClass.GetMethod("Run", BindingFlags.Public | BindingFlags.Static).Invoke(null, null);
You could really, really, really optimize your code a lot by paying the price of creating the delegate only once (there's also no need to instantiate the class to call an static method). I've done something very similar, and I just cache a delegate to the "Run" method with the help of a helper class :-). It looks like this:
static class Indent{
public static void Run(){
// implementation
}
// other helper methods
}
static class MacroRunner {
static MacroRunner() {
BuildMacroRunnerList();
}
static void BuildMacroRunnerList() {
macroRunners = System.Reflection.Assembly.GetExecutingAssembly()
.GetTypes()
.Where(x => x.Namespace.ToUpper().Contains("MACRO"))
.Select(t => (Action)Delegate.CreateDelegate(
typeof(Action),
null,
t.GetMethod("Run", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public)))
.ToList();
}
static List<Action> macroRunners;
public static void Run() {
foreach(var run in macroRunners)
run();
}
}
It is MUCH faster this way.
If your method signature is different from Action you could replace the type-casts and typeof from Action to any of the needed Action and Func generic types, or declare your Delegate and use it. My own implementation uses Func to pretty print objects:
static class PrettyPrinter {
static PrettyPrinter() {
BuildPrettyPrinterList();
}
static void BuildPrettyPrinterList() {
printers = System.Reflection.Assembly.GetExecutingAssembly()
.GetTypes()
.Where(x => x.Name.EndsWith("PrettyPrinter"))
.Select(t => (Func<object, string>)Delegate.CreateDelegate(
typeof(Func<object, string>),
null,
t.GetMethod("Print", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public)))
.ToList();
}
static List<Func<object, string>> printers;
public static void Print(object obj) {
foreach(var printer in printers)
print(obj);
}
}
Class that will call the methods:
namespace myNamespace
{
public class myClass
{
public static void voidMethodWithoutParameters()
{
// code here
}
public static string stringReturnMethodWithParameters(string param1, string param2)
{
// code here
return "output";
}
}
}
Calling myClass static methods using Reflection:
var myClassType = Assembly.GetExecutingAssembly().GetType(GetType().Namespace + ".myClass");
// calling my void Method that has no parameters.
myClassType.GetMethod("voidMethodWithoutParameters", BindingFlags.Public | BindingFlags.Static).Invoke(null, null);
// calling my string returning Method & passing to it two string parameters.
Object methodOutput = myClassType.GetMethod("stringReturnMethodWithParameters", BindingFlags.Public | BindingFlags.Static).Invoke(null, new object[] { "value1", "value1" });
Console.WriteLine(methodOutput.ToString());
Note: I don't need to instantiate an object of myClass to use it's methods, as the methods I'm using are static.
Great resources:
How C# Reflection Works
MethodBase.Invoke Method
I prefer simplicity...
private void _InvokeNamespaceClassesStaticMethod(string namespaceName, string methodName, params object[] parameters) {
foreach(var _a in AppDomain.CurrentDomain.GetAssemblies()) {
foreach(var _t in _a.GetTypes()) {
try {
if((_t.Namespace == namespaceName) && _t.IsClass) _t.GetMethod(methodName, (BindingFlags.Static | BindingFlags.Public))?.Invoke(null, parameters);
} catch { }
}
}
}
Usage...
_InvokeNamespaceClassesStaticMethod("mySolution.Macros", "Run");
But in case you're looking for something a little more robust, including the handling of exceptions...
private InvokeNamespaceClassStaticMethodResult[] _InvokeNamespaceClassStaticMethod(string namespaceName, string methodName, bool throwExceptions, params object[] parameters) {
var results = new List<InvokeNamespaceClassStaticMethodResult>();
foreach(var _a in AppDomain.CurrentDomain.GetAssemblies()) {
foreach(var _t in _a.GetTypes()) {
if((_t.Namespace == namespaceName) && _t.IsClass) {
var method_t = _t.GetMethod(methodName, parameters.Select(_ => _.GetType()).ToArray());
if((method_t != null) && method_t.IsPublic && method_t.IsStatic) {
var details_t = new InvokeNamespaceClassStaticMethodResult();
details_t.Namespace = _t.Namespace;
details_t.Class = _t.Name;
details_t.Method = method_t.Name;
try {
if(method_t.ReturnType == typeof(void)) {
method_t.Invoke(null, parameters);
details_t.Void = true;
} else {
details_t.Return = method_t.Invoke(null, parameters);
}
} catch(Exception ex) {
if(throwExceptions) {
throw;
} else {
details_t.Exception = ex;
}
}
results.Add(details_t);
}
}
}
}
return results.ToArray();
}
private class InvokeNamespaceClassStaticMethodResult {
public string Namespace;
public string Class;
public string Method;
public object Return;
public bool Void;
public Exception Exception;
}
Usage is pretty much the same...
_InvokeNamespaceClassesStaticMethod("mySolution.Macros", "Run", false);

Temporary store a Delegate for calling later

I want to use a list as storing actions to a framework while making async operations.
Then later when the framework synchronizes, then I will loop trought the list and perform the actions.
Is there a way to do this, with this in focus:
- No Reflection/DynamicInvoke.
- Not creating classes/structs for each new method to call.
- Type safe.
- store the actions in a list.
- store different kinds of methods and parameters.
- Execute the list later.
The reason I don't want to use reflection, is because it is a performance concern. It is gonna be use very frequently.
In this case, it is game related, but the code can be used as an allround, and would be excellent for multithreading, if reflection/DynamicInvoke could be avoided.
If this is not possible, then are there other nice alternatives?
I've made an example in code, but it uses reflection and isn't type safe.
Basicly the steps are:
1. Populate a list with methods with multiple different parameters.
2. Loop through the list & execute all methods with there parameters.
3. Clear the list for the next cycle.
{
struct MyDelayedCaller
{
public Delegate TheTarget;
public object[] MyParameters;
public MyDelayedCaller(Delegate target, object[] parameters)
{
TheTarget = target;
MyParameters = parameters;
}
}
List<MyDelayedCaller> Temporary = new List<MyDelayedCaller>();
void Update()
{
//something happened and another class needs to know
//but it will have to wait for the sync so as to not cause any treading problems
Temporary.Add(new MyDelayedCaller(new DelDoSomething1(DoSomething1), new object[] { 10, false }));
Temporary.Add(new MyDelayedCaller(new DelDoSomething1(DoSomething1), new object[] { 11, true }));
Temporary.Add(new MyDelayedCaller(new DelDoSomething3(DoSomething3), new object[] { "Some text" }));
Temporary.Add(new MyDelayedCaller(new DelDoSomething2(DoSomething2), new object[] { 1, 9999, 0.4f }));
}
void Sync()
{
foreach (var item in Temporary)
{
item.TheTarget.DynamicInvoke(item.MyParameters);
}
Temporary.Clear();
}
delegate void DelDoSomething1(int index, bool alive);
void DoSomething1(int index, bool alive)
{
}
delegate void DelDoSomething2(int index, int amount, float scale);
void DoSomething2(int index, int amount, float scale)
{
}
delegate void DelDoSomething3(string text);
void DoSomething3(string text)
{
}
}
I hope I understand the question because the answer seems so simple: Just store a List<Action>. You can put whatever you want in there. You can enumerate the list and call everything.
You absolutely can add parameterized calls to such a list: () => DoSomething1(10, false). The parameters are packaged inside of the Action. The C# compiler generates a (strongly-typed) closure class and does all of that for you.
Doesn't this do what you want?
I would go with following:
IMyDelayedCaller interface:
interface IMyDelayedCaller
{
void Invoke();
}
Set of MyDelayedCaller generic classes:
class MyDelayedCaller<T1> : IMyDelayedCaller
{
private Action<T1> _target;
public T1 _param;
public MyDelayedCaller(Action<T1> target, T1 parameter)
{
_target = target;
_param = parameter;
}
public void Invoke()
{
_target(_param);
}
}
class MyDelayedCaller<T1, T2> : IMyDelayedCaller
{
private Action<T1, T2> _target;
public T1 _param1;
public T2 _param2;
public MyDelayedCaller(Action<T1, T2> target, T1 param1, T2 param2)
{
_target = target;
_param1 = param1;
_param2 = param2;
}
public void Invoke()
{
_target(_param1, _param2);
}
}
I only showed for up to 2 parameters, you can make more if you need.
Change your list to List<IMyDelayedCaller>:
List<IMyDelayedCaller> Temporary = new List<IMyDelayedCaller>();
Add items to the list with compile time type safety:
Temporary.Add(new MyDelayedCaller<int, bool>(DoSomething1, 10, true));
Temporary.Add(new MyDelayedCaller<string>(DoSomething3, "Some text"));
Invoke using interface method:
foreach (var item in Temporary)
{
item.Invoke();
}
Temporary.Clear();
You can make stop 4. easier by providing static class which will allow your type parameters be inferred by compiler:
static class MyDelayedCaller
{
public static MyDelayedCaller<T1> Create<T1>(Action<T1> target, T1 param)
{
return new MyDelayedCaller<T1>(target, param1);
}
public static MyDelayedCaller<T1, T2> Create<T1, T2>(Action<T1, T2> target, T1 param1, T2 param2)
{
return new MyDelayedCaller<T1, T2>(target, param1, param2);
}
}
and usage:
Temporary.Add(MyDelayedCaller.Create(DoSomething1, 10, true));
Temporary.Add(MyDelayedCaller.Create(DoSomething3, "Some text"));
You could queue up your inputs and actions in parallel collections:
var actions = new Dictionary<int, Func<object[], object>>();
var inputs = new Dictionary<int, object[]>();
//when you want to store the action and it's input
int counter = 0;
object[] someObjects = new object[] {};
actions.Add(counter, x => { return x[0]; });
inputs.Add(counter, someObjects);
counter++;
//and then later when it's time to execute
foreach (var input in inputs)
{
actions[input.Key].Invoke(input.Value);
}
Alternatively, you could roll a class that stores both the input and the action, so the input is coupled to the action at execution time by something other than a matching dictionary key.
My other answer shows quite complicated way to do that. There is however one much easier. Why don't you make your list List<Action>?
List<Action> Temporary = new List<Action>();
void Update()
{
//something happened and another class needs to know
//but it will have to wait for the sync so as to not cause any treading problems
Temporary.Add(() => DoSomething1(1, true));
Temporary.Add(() => DoSomething3("Some text"));
}
void Sync()
{
foreach (var item in Temporary)
{
item.Invoke();
}
Temporary.Clear();
}
Should work just fine.
#Eli, you're getting 4's as the input value in your for loop because execution of the actions is deferred. When they actually execute, i = 4;
To avoid this, queue up your inputs.
I'd respond to your comment with a comment, but don't have the rep yet.

Handle Generic methods in a dictionary according to type

I have a generic method
public delegate void Handler<T>(T val);
I enable users to register to events and provide this delegate.
I need to save the list of delegate according to their types.
I tried saving in a dictionary of Type and object. when adding the method I cast it to a
List<Handler<T>>
according to the T. but then when an event occurred I do not have the T so cannot cast to the relevant list of generic handlers (I do have the Type but not the T)
I solved this by saving methodInfo list for each type
private Dictionary<Type, List<MethodInfo>> handlers = new Dictionary<Type, List<MethodInfo>>();
public delegate void Handler<T>(T val);
public void Register<T>( Handler<T> handler )
{
List<MethodInfo> lst;
if (!handlers.TryGetValue(typeof(T), out lst))
{
lst = new List<MethodInfo>();
handlers.Add(typeof(T), lst);
}
lst.Add(handler.Method);
}
public void RaiseEvent( string value)
{
foreach (KeyValuePair<Type, List<MethodInfo>> pair in handlers)
{
object typedValue;
if (pair.Key.IsEnum)
{
typedValue = Enum.Parse(pair.Key, value);
}
else
{
typedValue = Convert.ChangeType(value, pair.Key);
}
foreach (MethodInfo methodInfo in pair.Value )
{
methodInfo.Invoke(null, new[] { typedValue });
}
}
}
}
but the problem is that this approach will work only if the method is static , otherwise it will require the type of class.
is there any solution for this problem???
enable generic events...
thanks!
Maybe this will help:
public delegate void Handler<in T>(T val);
private List<Delegate> m_list = new List<Delegate>();
public void AddListener<T>(Handler<T> handler) {
m_list.Add(handler);
}
public void Call(object eventArg) {
foreach (var handler in m_list) {
handler.DynamicInvoke(eventArg);
}
}
Then, if you have a handler like this:
private void MyHandler(int val) {
// Do something
}
You can add it to the list like this:
AddListener<int>(MyHandler);
(This assumes I correctly understood what you're trying to do. I'm not sure though.)
You could also make a handler repository using a non-generic delegate, something like:
public delegate void Handler(object val);
public delegate void Handler<T>(T val);
public class HandlerRepository
{
private Dictionary<Type, Handler> handlers = new Dictionary<Type, Handler>();
public void RegisterHandler<T>(Handler<T> handler)
{
//error checking omitted
//create a non-generic handler that calls the generic handler
//with the correct type.
handlers.Add(typeof(T), (value)=>handler((T)value));
}
public void ExecuteHandler<T>(T value)
{
//error checking ommited
handlers[typeof(T)](value);
}
}
and use it like this:
Handler<int> handleInt = value => Console.WriteLine("Int32 is {0}", value);
Handler<string> handleString = value => Console.WriteLine("String is {0}", value);
HandlerRepository repo = new HandlerRepository();
repo.RegisterHandler(handleInt);
repo.RegisterHandler(handleString);
//this call boxes the argument to an object
repo.ExecuteHandler(5); // "Int32 is 5"
repo.ExecuteHandler("Hello, world"); "String is Hello, world"

C# - Passing all the method arguments to another method?

I've got a class, which has three overloaded methods. Let's say, there is:
class MyChildClass
{
public void myMethod(int i)
{ /* do something with i */ }
public void myMethod(int a, string b)
{ /* get i from a and b and call: */ myMethod(i); }
public void myMethod(string c, string d)
{ /* get i from c and d and call: */ myMethod(i); }
}
Now I'd like this class to be a private field in other (parent) class, but I need those three methods to be accessible. For now, I just did:
class MyBaseClass
{
private MyChildClass myObject = new myChildClass(); // or similar
public void myMethod(int i)
{ myObject.myMethod(i); }
public void myMethod(int a, string b)
{ myObject.myMethod(a, b); }
public void myMethod(string c, string s)
{ myObject.myMethod(c, d); }
}
Is there a way to implement it as one short method? Something which would look like:
public void myMethod(unknownListOfArgumentsOfDifferentTypes args)
{ myObject.myMethod(args); }
I tried to use public void myMethod(params object[] something) but it didn't work. Is it possible, or do I have to "project" every method into another?
EDIT: Child class has various methods and fields, which I want to be accessible for parent class only. That's why I don't want parent to derive after it. I didn't explain that, sorry if it looked like child class contains only those three methods. Those are the methods I want to be accessible as public methods of parent class.
Why don't you do
class MyChildClass : MyBaseClass
{
}
same effect, less code, and this way MyChildClass is a MyBaseClass
If you implement some sort of generic facade using reflection you'll just be reducing performance, bypassing the benefits of type safety and delaying the discovery of problems.
You'll also have have a "has a" relationship instead "is a" relationship which is incongruent with your class names.
If you want to give up this simplicty with its associated benefits you could make use the GetMethodBySig extension accepted in this post.
Something like this,
class SemiGenericFacade<T> where T : new()
{
private readonly t = new T();
public void CallVoidOnT(string name, params object[] parameters)
{
var paramTypes = parameters.Select(p => typeof(p))
var match = typeof(T).GetMethodBySig(typeof(void), paramTypes)
.Single(mi => mi.Name == name);
match.Invoke(this.t, parameters);
}
}
Following on from Piotr Justyna's comment, implementing and using this method results in the cat turning into a tiger and eating her kittens.
If you were to do this it would make sense to add to the linked extension
public static class Extensions
{
public static MethodInfo GetMethodByNameThenSig(
this Type type,
string name,
Type returnType,
params Type[] parameterTypes)
{
return type.GetMethods().Where((m) =>
{
if (m.Name != name)
{
return false;
}
if (m.ReturnType != returnType)
{
return false;
}
var parameters = m.GetParameters();
if ((parameterTypes == null || parameterTypes.Length == 0))
{
return parameters.Length == 0;
}
if (parameters.Length != parameterTypes.Length)
{
return false;
}
for (int i = 0; i < parameterTypes.Length; i++)
{
if (parameters[i].ParameterType != parameterTypes[i])
{
return false;
}
}
return true;
}).Single();
}
}
Which you could use like this,
class GenericFacade<T> where T : new()
{
private readonly t = new T();
public void CallOnInternal(string name, params object[] parameters)
{
var paramTypes = parameters.Select(p => typeof(p))
var match = typeof(T).GetMethodByNameThenSig(
name,
typeof(void),
paramTypes);
match.Invoke(this.t, parameters);
}
public TResult CallOnInternal<TResult>(string name, params object[] parameters)
{
var paramTypes = parameters.Select(p => typeof(p))
var match = typeof(T).GetMethodByNameThenSig(
name,
typeof(TResult),
paramTypes);
return (TResult)match.Invoke(this.t, parameters);
}
}
FINAL EDIT
Looking at the code involved to use reflection and considering the cost associated with the loss of type safety. I'd suggest its better to establish the "has-a" relationship explicitly in the traditional manner.
You can use public void myMethod(params object[] something) as in:
public static void Main()
{
UnknownArgumentsMethod1(1, 2, 3, "foo");
}
public static void UnknownArgumentsMethod1(params object[] list)
{
UnknownArgumentsMethod2(list);
}
public static void UnknownArgumentsMethod2(params object[] list)
{
foreach (object o in list)
{
if (o.GetType() == typeof(int))
{
Console.WriteLine("This is an integer: " + (int)o);
}
else if (o.GetType() == typeof(string))
{
Console.WriteLine("This is a string: " + (string)o);
}
}
}
The obvious answer would be to have inheritance.
In your case (even though the names of the classes suggest otherwise) the way to do it is by inheriting the ChildClass in the BaseClass and that way you would have the methods from the ChildClass exposed through the BaseClass.
ex:
class MyBaseClass: MyChildClass
{
}
If the classes are not related and you just want to have an instance of MyChildClass in MyBaseClass but only expose a certain set of methods but by not making the others private what you could do is expose the MyChildClass instance through an interface that only exposes the necessary fields like so:
public class BaseClass
{
public IChildClass ChildClassInstance = new ChildClass();
}
public class ChildClass : IChildClass
{
public void myMethod(int i)
{ /* do something with i */ }
public void myMethod(int a, string b)
{ /* get i from a and b and call: */ myMethod(i); }
public void myMethod(string c, string d)
{ /* get i from c and d and call: */ myMethod(i); }
}
public interface IChildClass
{
void myMethod(int i);
void myMethod(int a, string b);
}
and then you could access only the methods that you allow to be exposed through an instance of the base class:
BaseClass test = new BaseClass();
test.ChildClassInstance.myMethod(1);
test.ChildClassInstance.myMethod(1,"test");

Double Dispatch [duplicate]

I have heard/read the term but don't quite understand what it means.
When should I use this technique and how would I use it? Can anyone provide a good code sample?
The visitor pattern is a way of doing double-dispatch in an object-oriented way.
It's useful for when you want to choose which method to use for a given argument based on its type at runtime rather than compile time.
Double dispatch is a special case of multiple dispatch.
When you call a virtual method on an object, that's considered single-dispatch because which actual method is called depends on the type of the single object.
For double dispatch, both the object's type and the method sole argument's type is taken into account. This is like method overload resolution, except that the argument type is determined at runtime in double-dispatch instead of statically at compile-time.
In multiple-dispatch, a method can have multiple arguments passed to it and which implementation is used depends on each argument's type. The order that the types are evaluated depends on the language. In LISP, it checks each type from first to last.
Languages with multiple dispatch make use of generic functions, which are just function delcarations and aren't like generic methods, which use type parameters.
To do double-dispatch in C#, you can declare a method with a sole object argument and then specific methods with specific types:
using System.Linq;
class DoubleDispatch
{
public T Foo<T>(object arg)
{
var method = from m in GetType().GetMethods()
where m.Name == "Foo"
&& m.GetParameters().Length==1
&& arg.GetType().IsAssignableFrom
(m.GetParameters()[0].GetType())
&& m.ReturnType == typeof(T)
select m;
return (T) method.Single().Invoke(this,new object[]{arg});
}
public int Foo(int arg) { /* ... */ }
static void Test()
{
object x = 5;
Foo<int>(x); //should call Foo(int) via Foo<T>(object).
}
}
The code posted by Mark isn't complete and what ever is there isn't working.
So tweaked and complete.
class DoubleDispatch
{
public T Foo<T>(object arg)
{
var method = from m in GetType().GetMethods(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic)
where m.Name == "Foo"
&& m.GetParameters().Length == 1
//&& arg.GetType().IsAssignableFrom
// (m.GetParameters()[0].GetType())
&&Type.GetType(m.GetParameters()[0].ParameterType.FullName).IsAssignableFrom(arg.GetType())
&& m.ReturnType == typeof(T)
select m;
return (T)method.Single().Invoke(this, new object[] { arg });
}
public int Foo(int arg)
{
return 10;
}
public string Foo(string arg)
{
return 5.ToString();
}
public static void Main(string[] args)
{
object x = 5;
DoubleDispatch dispatch = new DoubleDispatch();
Console.WriteLine(dispatch.Foo<int>(x));
Console.WriteLine(dispatch.Foo<string>(x.ToString()));
Console.ReadLine();
}
}
Thanks Mark and others for nice explanation on Double Dispatcher pattern.
C# 4 introduces the pseudo type dynamic which resolves the function call at runtime (instead of compile time). (That is, the runtime type of the expression is used). Double- (or multi-dispatch) can be simplified to:
class C { }
static void Foo(C x) => Console.WriteLine(nameof(Foo));
static void Foo(object x) => Console.WriteLine(nameof(Object));
public static void Main(string[] args)
{
object x = new C();
Foo((dynamic)x); // prints: "Foo"
Foo(x); // prints: "Object"
}
Note also by using dynamic you prevent the static analyzer of the compiler to examine this part of the code. You should therefore carefully consider the use of dynamic.
The other answers use generics and the runtime type system. But to be clear the use of generics and runtime type system doesn't have anything to do with double dispatch. They can be used to implement it but double dispatch is just dependent on using the concrete type at runtime to dispatch calls. It's illustrated more clearly I think in the wikipedia page. I'll include the translated C++ code below. The key to this is the virtual CollideWith on SpaceShip and that it's overridden on ApolloSpacecraft. This is where the "double" dispatch takes place and the correct asteroid method is called for the given spaceship type.
class SpaceShip
{
public virtual void CollideWith(Asteroid asteroid)
{
asteroid.CollideWith(this);
}
}
class ApolloSpacecraft : SpaceShip
{
public override void CollideWith(Asteroid asteroid)
{
asteroid.CollideWith(this);
}
}
class Asteroid
{
public virtual void CollideWith(SpaceShip target)
{
Console.WriteLine("Asteroid hit a SpaceShip");
}
public virtual void CollideWith(ApolloSpacecraft target)
{
Console.WriteLine("Asteroid hit ApolloSpacecraft");
}
}
class ExplodingAsteroid : Asteroid
{
public override void CollideWith(SpaceShip target)
{
Console.WriteLine("ExplodingAsteroid hit a SpaceShip");
}
public override void CollideWith(ApolloSpacecraft target)
{
Console.WriteLine("ExplodingAsteroid hit ApolloSpacecraft");
}
}
class Program
{
static void Main(string[] args)
{
Asteroid[] asteroids = new Asteroid[] { new Asteroid(), new ExplodingAsteroid() };
ApolloSpacecraft spacecraft = new ApolloSpacecraft();
spacecraft.CollideWith(asteroids[0]);
spacecraft.CollideWith(asteroids[1]);
SpaceShip spaceShip = new SpaceShip();
spaceShip.CollideWith(asteroids[0]);
spaceShip.CollideWith(asteroids[1]);
}
}
Full listing of working code
using System;
using System.Linq;
namespace TestConsoleApp
{
internal class Program
{
public static void Main(string[] args)
{
const int x = 5;
var dispatch = new DoubleDispatch();
Console.WriteLine(dispatch.Foo<int>(x));
Console.WriteLine(dispatch.Foo<string>(x.ToString()));
Console.ReadLine();
}
}
public class DoubleDispatch
{
public T Foo<T>(T arg)
{
var method = GetType()
.GetMethods()
.Single(m =>
m.Name == "Foo" &&
m.GetParameters().Length == 1 &&
arg.GetType().IsAssignableFrom(m.GetParameters()[0].ParameterType) &&
m.ReturnType == typeof(T));
return (T) method.Invoke(this, new object[] {arg});
}
public int Foo(int arg)
{
return arg;
}
public string Foo(string arg)
{
return arg;
}
}
}

Categories