2012-10-12 39 views
1

我对C#相当陌生,并且正在开发一种实现动态GUI的方式,这种方式使用串行通信。我最初来自C,所以函数指针的概念很熟悉。存储/传递代表作为变量

基本上,我想在串行命令处理完成后调用answerFunction()函数。 理论上: 我有一个在运行时动态创建的类lbl_txtBox_Pair。 我有一个与串行端口通信的comObject类。 我有第三类comPacket,它包含有关一个串行命令的所有信息。

  1. 在类对象中的lbl_txtBox_Pair我实例化一个包并告诉它当串行命令完成时应该调用哪个函数。
  2. 我将包对象赋给comObject实例。
  3. 经过beeing处理后,comObject想要通过调用存储在数据包对象中的委托来发信号通知数据包的原始发送者。

由于某种原因,我无法让它工作。它告诉我包的属性不可调用。我做的事情大错特错吗?

这里是代码: 首先是类“lbl_txtBox_Pair”中的代码。我在这里创建comPacket并将其提供给comObject。

public delegate void answerHandler(comPacket packet); 
public void txb_value_KeyPress(object sender, KeyPressEventArgs e) 
{ 
    if (e.KeyChar == (char)Keys.Return) 
    { 
     answerHandler answerMethod = new answerHandler(this.processAnswer); 
     comPacket question = new comPacket(this.command, answerMethod, 1); 
     comObject.addPacket(question); 
    } 
} 

comPacket的构造函数。这里委托被存储以后再调用。

public Delegate answerFunction; 
public comPacket(string cmd, Delegate func, int prio) 
{ 
    this.cmd = cmd; 
    answerFunction = func; 
    this.prio = prio; 
} 

在comObject数据包得到处理。完成后,我想调用存储在数据包中的函数。顺便说一句,comObject运行在不同的线程中。

if (this.isEndtocken(inputline)) 
{ 
    listen = false; 
    packet.answerFunction(packet); 
} 

这里是它被打破。 packet.answerFunction(分组);不会执行,并说它不能被称为方法。

任何人都可以看到它出错哪里?我认为,代表似乎认为这是一个委托或某事的信息。 ;) 或者我必须完全重构代码才能使用其他类型的回调/事件方法?

+0

这是编译器消息还是运行时失败?你能否发布你正在收到的确切消息? – Vlad

+0

顺便说一句,如果'funk'只是'Delegate',你不能用参数调用它。也许你需要'answerHandler'来代替? (在'comPacket'内) – Vlad

回答

2

更改comPacket采取一个强类型的委托:

public answerHandler answerFunction; 
public comPacket(string cmd, answerHandler func, int prio) 
{ 
    this.cmd = cmd; 
    answerFunction = func; 
    this.prio = prio; 
} 

如果你仍想保留委托引用弱类型,您可以利用DynamicInvoke代替:http://msdn.microsoft.com/en-us/library/system.delegate.dynamicinvoke.aspx

编辑:另一种选择,如果你想维护强类型的代表,但有不同的用法是利用泛型。您的委托可以安置在通用类中,并将其签名与该通用类型绑定。

+0

谢谢Chris, 我现在所做的是我使用强类型。我不能在lbl_txtBox_Pair类中定义委托类型,因为这样我只能在这个类中使用这种类型的委托。因此它需要变弱。 但是,当它在comObject类中定义时,我可以在比lbl_txtBox_Pair更多的类中引用它。 – Bydlo

0

我不能留下评论,所以我必须将其作为回答发布。 委托人(以及事件和东西)通常只能由包含它们的对象“调用”。

所以,如果你有

class MyClass { 
    public event Action someEvent; 
    // you can also replace Action with the name of your delegate type 
} 

,并尝试做

MyClass x = new MyClass(); 
x.someEvent.Invoke(); 

那么这是一个错误。如果你想其它对象能够调用的情况下,你必须做一个方法添加到MyClass这样的:

public void InvokeMyEvent() { 
    someEvent.Invoke(); 
} 

(我忘了,你是否仍然要为静态事件做到这一点)

+1

只有当您使用'event'关键字声明它们时才是这种情况。代表只是可以传递并无条件地调用的对象。如果你不用'event'来标记你的委托,它可以被_anything_调用,它可以访问它。无论如何,这不是问题所在。 –

+0

@ChrisSinclair哦,所以这就是为什么'event'关键字是“可选”的原因...... – Pyritie