Pass Method as Parameter using C# with Parameters - Using the Command Pattern - c#

I'm new to passing delegates and was wondering if the following code is possible to do?
CommandQueue.AddCommand(
new CommandItem(
group.MyGroupActionMovement(
new Vector3(-1000,-1000,-1000))));
ok to elaborate I'm going to do a code dump of my bad attempt at the command pattern...
So I'm trying to create a queue of commands. Starting with just the movement command. It takes a vector3 as a parameter. Other Commands will have different parameters like enums and game objects.
This is supposed to be my interface for commands/actions but, I've been messing with it to see what I can do.
public class IGroupAction: MonoBehaviour
{
public delegate bool Del(Vector3 destination);
public virtual bool Execute()
{
return true;
}
}
This is supposed to be the command/action unit/item
public class GroupActionItem
{
public IGroupAction MyGroupAction;
public GroupActionItem(IGroupAction.Del action)
{
}
public bool PerformAction()
{
return MyGroupAction.Execute();
}
}
This is the command pattern that I've completed so far
public class GroupAction
{
public List<GroupActionItem> Actions;
public GroupAction()
{
Actions = new List<GroupActionItem>();
}
public void AddAction(GroupActionItem groupActionItem)
{
Actions.Add(groupActionItem);
}
public void ClearActions()
{
Actions.Clear();
}
public void PerformActions()
{
if (Actions.Count >= 1)
{
if(Actions[0].PerformAction())
{
Actions.Remove(Actions[0]);
}
}
}
}
This is where I execute the movement command
public class GroupActionMovement : IGroupAction
{
public override bool Execute()
{
return Movement();
}
public bool Movement(Vector3 destination)
{
return true;
}
}
public class Group : MonoBehaviour
{
public GroupActionMovement MyGroupActionMovement;
}
This is the execution of the coded behavior.
public class Player : MonoBehaviour
{
public Dictionary<Group,GroupAction> PlayerGroupsActions;
public List<Group> Groups;
void Start()
{
PlayerGroupsActions = new Dictionary<Group, GroupAction>();
Groups = GetComponentsInChildren<Group>().ToList();
foreach (Group group in Groups)
{
GroupAction playerGroupActions = new GroupAction();
PlayerGroupsActions.Add(group,playerGroupActions);
}
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Alpha1))
{
//remove the foreach
foreach (Group group in Groups)
{
//directly apply the group
PlayerGroupsActions.TryGetValue(group, out GroupAction playerGroupActions);
if (playerGroupActions != null)
{
playerGroupActions.AddAction(new GroupActionItem(group.MyGroupActionMovement.Movement));
}
}
}
foreach (Group group in Groups)
{
PlayerGroupsActions.TryGetValue(group, out GroupAction playerFormationActions);
if (playerFormationActions != null)
{
if (playerFormationActions.Actions.Count != 0)
{
playerFormationActions.PerformActions();
}
}
}
}
}
I'm sorry if this isn't the best explanation of what is going on or, that a code dump is not the best way to explain what i'm doing.

don't pass it as a method, use something like this
CommandQueue.Command += doSomething;
void doSomething()
{
//doSomething
}
So that whenever the function CommandQueue.Command is run in the seperate class it will also run the doSomething() void in the main class

A delegate is not a method call, but the method it self, for the receiver to call it, whenever its needs to, with the parameters it wants.
Here is an example:
public delegate int MyDelegate(Vector3 vec);
public class MyCallingClass
{
public void DoSomething(MyDelegate method)
{
// Do something.
int result = method(new Vector3(-1000, -1000, -1000));
// Do something else.
}
}
public class MyClass
{
public static int MyStaticMethod(Vector3 arg)
{
// Do something with arg.
return x;
}
int MyMethod(Vector3 arg)
{
// Do something with arg.
return x;
}
private void DelegateWork()
{
MyCallingClass c = // Get an instance of MyCallingClass.
c.DoSomething(this.MyMethod);
c.DoSomething(MyClass.MyStaticMethod);
}
}
Multiple things to understand here:
At line c.DoSomething(this.MyMethod), the this is captured into the delegate you pass, meaning that when MyCallingClass.DoSomething will call the delegate, it will be called on the instance of MyClass. The line c.DoSomething(MyClass.MyStaticMethod) will call it with no instance, because it is a static method.
This is the method MyCallingClass.DoSomething that decides what parameters to pass, not the one that provides the delegate.
If you need the caller to provide arguments and the calling part to just decide when to call but not deciding what arguments to pass, then you can capture the argument ahead of time, and pass a delegate without argument, as follow.
public delegate int MyDelegate(); // No arguments anymore.
public class MyCallingClass
{
public void DoSomething(MyDelegate method)
{
// Do something.
int result = method(); // Not passing arguments anymore.
// Do something else.
}
}
public class MyClass
{
// ...
private void DelegateWork()
{
MyCallingClass c = // Get an instance of MyCallingClass.
c.DoSomething(() => this.MyMethod(new Vector3(-1000, -1000, -1000)));
c.DoSomething(() => MyClass.MyStaticMethod(new Vector3(-1000, -1000, -1000));
}
}
If you are not familiar with the syntax () => ..., this is a lambda expression, you can see it as an anonymous function created on-the-fly. It still respects the prototype returning an int and taking no parameters. The lambda expression now captures the construction of the Vector3 instance, and so this value will be used when the lambda will be called. A very important aspect to understand is that the values in the lambda expressions are evaluated when the lambda is called, not when it is created (lazy evaluation).
You do not have to use a specific delegate but instead you can use a Func<Vector3, int>, as follow:
// Not actually needed.
// public delegate int MyDelegate(Vector3 vec);
public class MyCallingClass
{
public void DoSomething(Func<Vector3, int> method)
{
...
}
}

Related

Pass different data types into function that returns nothing

I have a class method that returns nothing but modifies an instance variable of the current object, it needs to be able to take in two different data types as the same parameter (An instance of the class or a number).
public class MyClass
{
public void MyMethod([EITHER MyClass x OR double x])
{
if(x is MyClass)
{
//do something
}
else
{
//do something else
}
}
You can overload the method MyMethod like below.
public void MyMethod(MyClass x) {
}
public void MyMethod(double x) {
}
Use method overloading as:
public class MyClass
{
public void MyMethod(MyClass x)
{
// do anything with MyClass
}
public void MyMethod(double x)
{
// do anything with double
}
}
Please check if below may be helpful.
public static void MyTestObjectClass(object value)
{
Type getTypeOfParam = value.GetType();//Get type of parameters.
//Handle on getTypeOfParam, you will get namespace.yourType
if(getTypeOfParam==?)
{
//Then do here
}
}

Interface particular properties

How to solve this problem about interfaces? I think I need this variable (and some others)in this especific class.
public interface Action
{
void execute();
}
public A:Action
{
public int misteriousNumber;
void execute()
{
int iUseMisteriousNumber = misteriousNumber;
}
}
public B:Action
{
void execute()
{
//I use nothing.
}
}
//Some Class...
static void Main(string[] args)
{
foreach(Action action in SecretRepositoryOfTheActions.actions)
{
if(action is A)
(SomeTypeOfCasting to A)action.misteriousNumber=13;
action.execute();
}
}
Just the 'A' class have this property not other Action classes what to use to access it (casting, not interfaces other implementation)?
You have to cast it, first check the type with is:
foreach(Action action in SecretRepositoryOfTheActions.actions)
{
if(action is A)
((A) action).misteriousNumber = 13;
action.execute();
}
If you only wanted to process A-objects (which doesn't seem to be the case):
foreach(A a in SecretRepositoryOfTheActions.actions.OfType<A>())
{
a.misteriousNumber = 13;
a.execute();
}

RegisterCallback<T>(Action<T> func) , how do I store this function pointer in a class?

I'm trying to expose an API such that, I do the following
RegisterCallback<T>(Action<T> func)
{
someObj.FuncPointer = func;
}
Later on, I call func(obj) .. and the obj is of type T that the user said.
More concrete example:
var callbackRegistrar = new CBRegistrar();
callbackRegistrar.RegisterCallback<ISomeClass>(SomeFunc);
public static void SomeFunc(ISomeClass data)
{
//
}
EDIT: So I may not have been clear, so I'll add more code:
I want to make only "one" object of CBRegistrar, and connect it with many Callbacks, as such:
var callbackRegistrar = new CBRegistrar();
callbackRegistrar.RegisterCallback<ISomeClass>(SomeFunc);
callbackRegistrar.RegisterCallback<ISomeOtherClass>(SomeFunc2);
...
In fact the above code is called by reflecting over a directory of plugins.
The user puts this in their code -->
public static void SomeFunc(ISomeClass data)
{
//
}
public static void SumFunc2(ISomeOtherClass data)
{
//
}
It looks to me as if this is not possible using Generics, etc. What it looks like I might have to do is make an interface called IPlugin or something, and ask the user to do this ..
[PluginIdentifier(typeof(ISomeClass))]
public static void SomeFunc(IPluginData data)
{
var castedStuff = data as ISomeClass; // ISomeClass inherits from IPluginData
}
Seems like asking the user to do stuff that we should take care of, but anyway ...
You need a Action<T> func to store it in. There is a semantic check to make here: if someone calls RegisterCallback twice (with different values), do you want to replace the callback, or keep both ? Assuming the latter, someObj probably wants an event (indeed, this entire API could be exposed as an event), so - in the someObj class:
public event Action<T> FuncPointer;
private void InvokeCallback(T data) {
var handler = FuncPointer;
if(handler != null) handler(data);
}
Noting that RegisterCallback could be replaced entirely, still keeping the data on obj:
public event Action<T> Completed {
add { obj.FuncPointer += value; }
remove { obj.FuncPointer -= value; }
}
Then usage would be:
var callbackRegistrar = new CBRegistrar();
callbackRegistrar.Completed += SomeFunc;
Callback functions are not much used in C#. They've been replaced by events which are more elegant and easier to work with.
class CBRegistrar
{
public delegate void ActionRequiredEventHandler(object sender, ISomeClass e);
public event ActionRequiredEventHandler ActionRequired;
void RaiseActionRequiredEvent(ISomeClass parm)
{
if ( ActionRequired != null)
{
ActionRequired(this, parm);
}
}
}
class APIConsumer
{
var callbackRegistrar = new CBRegistrar();
public APIConsumer()
{
callbackRegistrar.ActionRequired += SomeFunc;
}
public void SomeFunc(object sender, ISomeClass data)
{
}
}
If you still want to use Callbacks, you can use Delegates which are more or less function pointer.
The CBRegistrar will need to be generic (if it's OK to keep a single callback type) or it can do some internal casting (if several callback types need to be registered).
public class CBRegistrar<T>
{
private Action<T> callback;
private Dictionary<Type, object> callbackMap;
public CBRegistrar()
{
this.callbackMap = new Dictionary<Type, object>();
}
public void RegisterCallback(Action<T> func)
{
this.callback = func;
}
public void RegisterGenericCallback<U>(Action<U> func)
{
this.callbackMap[typeof(U)] = func;
}
public Action<U> GetCallback<U>()
{
return this.callbackMap[typeof(U)] as Action<U>;
}
}
public interface ISomeClass
{
string GetName();
}
public class SomeClass : ISomeClass
{
public string GetName()
{
return this.GetType().Name;
}
}
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
var callbackRegistrar = new CBRegistrar<ISomeClass>();
callbackRegistrar.RegisterCallback(SomeFunc);
callbackRegistrar.RegisterGenericCallback<ISomeClass>(SomeFunc);
var someone = new SomeClass();
callbackRegistrar.GetCallback<ISomeClass>()(someone);
}
public static void SomeFunc(ISomeClass data)
{
// Do something
Console.WriteLine(data.GetName());
}
}
}

read return value from delegate

I am not sure if I understood the usage of delegates correctly but I would like to read delegate return value in publisher class. The example is below with description.
//Publisher class
public class ValidateAbuse
{
public delegate List<String> GetAbuseList();
public static GetAbuseList Callback;
public void Ip(string ip)
{
// I would like to read GetAbuseList value (List<String>) here. How to do that?
}
}
//Subscriber class
class Server
{
public static void Start()
{
ValidateAbuse.Callback = GetIpAbuseList;
ValidateAbuse.Ip(MyIp);
}
private static List<string> GetIpAbuseList()
{
//return List<String> to ValidateAbuse class and use return value in public void Ip(string ip) method
}
public void Ip(string ip)
{
if (Callback != null)
{
List<String> valueReturnedByCallback = Callback();
}
}
Here's a version that does not use static for ValidateAbuse and that uses the built-in Func<T> delegate.
public class ValidateAbuse
{
private Func<List<string>> callback;
public ValidateAbuse(Func<List<string>> callback)
{
this.callback = callback;
}
public void Ip(string ip)
{
var result = callback();
}
}
public class Server
{
public static void Start()
{
var validateAbuse = new ValidateAbuse(GetIpAbuseList);
validateAbuse.Ip(MyIp);
}
private static List<string> GetIpAbuseList()
{
//return List<string> to ValidateAbuse class and use return value in public void Ip(string ip) method
}
}
I recommend you avoid static since that gives you a global state, which could later give you coupling problems and also makes it hard for you to unit test.
The other answers given so far has a guard clause, checking Callback for null. Unless that is expected behaviour (that Callback is null) I would avoid this. It's better to crash early than to get hard to debug errors later on.
I would also try to make the Server non-static.
It should be as simple as:
// Ip in your code sample is missing static
public static void Ip(string ip)
{
List<string> abuseList;
if (Callback != null)
abuseList = Callback()
}
However you can avoid creating a delegate all together by using a Func:
public static Func<List<string>> Callback;
Try this: Read more from here http://msdn.microsoft.com/en-us/library/bb534960%28v=vs.110%29.aspx
internal delegate int PowerOfTwo();
void Main(){
PowerOfTwo ch = new PowerOfTwo(CheckPower);
Console.WriteLine(ch());
}
int CheckPower(){
return 2*2;
}
#Torbjörn Kalin's answer is good, but only if you have only 1 delegate you want to get the return value from. If you want to retrieve the return values of more than one delegate, this is how you do it:
//Publisher class
public class ValidateAbuse
{
public delegate List<String> GetAbuseList();
public static GetAbuseList Callback;
public void Ip(string ip)
{
foreach (GetAbuseList gal in Callback.GetInvocationList())
{
List<string> result = gal.Invoke(/*any arguments to the parameters go here*/);
//Do any processing on the result here
}
}
}
//Subscriber class
class Server
{
public static void Start()
{
//Use += to add to the delegate list
ValidateAbuse.Callback += GetIpAbuseList;
ValidateAbuse.Ip(MyIp);
}
private static List<string> GetIpAbuseList()
{
//return code goes here
return new List<String>();
}
This will invoke each delegate one after the other, and you can process the output of each delegate separately from each other.
The key here is using the += operator (not the = operator) and looping through the list that is retrieved by calling GetInvocationList() and then calling Invoke() on each delegate retrieved.
I figured this out after reading this page:
https://www.safaribooksonline.com/library/view/c-cookbook/0596003390/ch07s02.html
(altho it was partially because I already had an idea what to do, and I didn't start a free trial to read the rest)
Hope this helps!

implementing delegates in c#

This would be the first time I'd use delegates in c# so please bear with me. I've read a lot about them but never thought of how/why to use this construct until now.
I have some code that looks like this:
public class DoWork()
{
public MethodWorkA(List<long> TheList) {}
public void MethodWork1(parameters) {}
public void MethodWork2(parameters) {}
}
I call MethodWorkA from a method outside the class and MethodWorkA calls MethodWork 1 and 2. When I call methodA, I'd like to pass some sort of parameter so that sometimes it just does MethodWork1 and sometimes it does both MethodWork1 and MethodWork2.
So when I call the call it looks like this:
DoWork MyClass = new DoWork();
MyClass.MethodA...
Where does the delegate syntax fit in this?
Thanks.
public void MethodWorkA(Action<ParamType1, ParamType2> method) {
method(...);
}
You can call it using method group conversion:
MethodWorkA(someInstance.Method1);
You can also create a multicast delegate that calls two methods:
MethodWorkA(someInstance.Method1 + someInstance.Method2);
For what you described, you don't need delegates.
Just do something like this:
public class DoWork
{
public void MethodWorkA(List<long> theList, bool both)
{
if (both)
{
MethodWork1(1);
MethodWork2(1);
}
else MethodWork1(1);
}
public void MethodWork1(int parameters) { }
public void MethodWork2(int parameters) { }
}
If you're just experimenting with delegates, here goes:
public partial class Form1 : Form
{
Func<string, string> doThis;
public Form1()
{
InitializeComponent();
Shown += Form1_Shown;
}
void Form1_Shown(object sender, EventArgs e)
{
doThis = do1;
Text = doThis("a");
doThis = do2;
Text = doThis("a");
}
string do1(string s)
{
MessageBox.Show(s);
return "1";
}
string do2(string s)
{
MessageBox.Show(s);
return "2";
}
}
Considering that all methods are inside the same class, and you call MethodWorkA function using an instance of the class, I honestly, don't see any reason in using Action<T> or delegate, as is I understood your question.
When I call methodA, I'd like to pass some sort of parameter so that
sometimes it just does MethodWork1 and sometimes it does both
MethodWork1 and MethodWork2.
Why do not just pass a simple parameter to MethodWorkA, like
public class DoWork()
{
public enum ExecutionSequence {CallMethod1, CallMethod2, CallBoth};
public MethodWorkA(List<long> TheList, ExecutionSequence exec)
{
if(exec == ExecutionSequence.CallMethod1)
MethodWork1(..);
else if(exec == ExecutionSequence.CallMethod2)
MethodWork2(..);
else if(exec == ExecutionSequence.Both)
{
MethodWork1(..);
MethodWork2(..);
}
}
public void MethodWork1(parameters) {}
public void MethodWork2(parameters) {}
}
Much simplier and understandable for your class consumer.
If this is not what you want, please explain.
EDIT
Just to give you an idea what you can do:
Example:
public class Executor {
public void MainMethod(long parameter, IEnumerable<Action> functionsToCall) {
foreach(Action action in functionsToCall) {
action();
}
}
}
and in the code
void Main()
{
Executor exec = new Executor();
exec.MainMethod(10, new List<Action>{()=>{Console.WriteLine("Method1");},
()=>{Console.WriteLine("Method2");}
});
}
The output will be
Method1
Method2
In this way you, for example, can push into the collection only functions you want to execute. Sure, in this case, the decision logic (which functions have to be executed) is determined outside of the call.

Categories

Resources