代表具体细节

时间:2011-02-04 18:23:36

标签: c# delegates xna

我正在处理正在进行的项目中的代理问题。该类是一个GUI组件,它接受标签和值。这里的想法是用户可以指定标签,然后从任何地方链接一个值(更具体地说,该值的ToString方法),以便每次更新该值时,GUI组件也是如此。这是它如何设置的基础:

public delegate string GUIValue();

public class GUIComponent
{
    GUIValue value = null;    // The value linked in
    string label = "";        // The label for the value
    string text = "";         // The label and value appended together

    public GUIComponent(string Text, GUIValue Value)
    {
        this.text = Text;
        this.value += Value;
    }

    public void Update()
    {
        this.text = this.label + this.value();
    }
}

然后我称之为

GUIComponent component = new GUIComponent("Label: ",
                                new GUIValue(this.attribute.ToString));

代码正确编译,组件显示,并显示给定属性的初始值,但是,只要属性值发生更改,它就不会更新。

我的问题是,我是否首先将此设置正确,如果是这样,为什么它不起作用。我最初的想法是它只接受ToString方法的第一个值返回,因为它不接受任何参数,但任何人都可以验证吗?

4 个答案:

答案 0 :(得分:1)

需要调用代理人 你所拥有的是value引用this.attribute.ToString方法。

这意味着当您调用this.value()时,将调用该函数。

当您更改this.attribute的值时,您可能通过将其引用到包含不同值的其他对象来实现此目的。
所以我猜你所遇到的是,每次拨打update()时,都会显示旧值。这是因为垃圾收集器不会破坏旧对象,因为您通过委托持有对它的引用。

当您更改属性的值时,GUI委托仍然保留旧对象的方法而不是新对象的方法。

答案 1 :(得分:1)

此代码:

new GUIValue(this.attribute.ToString)
每次属性更改时,

都不会导致调用该方法。您必须存储代理并在每次有人更改“属性”时调用它。类似的东西:

private event GUIValue attributeChanged = () => this.attribute.ToString();

private String attribute;

// This is a property that sets the value of attribute
public String Attribute { get { return attribute; } set { attribute = value; attributeChanged(); } }

// Now you can initialize the component using:
// GUIComponent component = new GUIComponent("Label: ", this.attributeChanged);

答案 2 :(得分:1)

你有一半。我认为正在发生的事情是,尽管你最初可以得到这个值,但是你的GuiComponent并没有告诉任何类实际拥有作为GUIValue委托给出的方法,该值实际已经改变并重新获得它。告诉其他对象事件发生的常规方法是一个事件,其他对象通过传入将在事件被引发时运行的委托来“订阅”。

以下是我构建代码的方法:

public interface IHaveAValueYouNeed 
{
    string ValueGetter();
    event EventArgs ValueChanged;
}

public class GUIComponent
{
    public delegate string ValueGetter();

    ValueGetter getter;    // The value linked in
    string label = "";        // The label for the value
    string text = "";         // The label and value appended together

    public GUIComponent(string Text, IHaveAValueYouNeed getter)
    {
        this.text = Text;
        this.getter += getter.ValueGetter;
        getter.ValueChanged += ValueUpdatedHandler;
    }

    public void Update()
    {
        this.text = this.label + this.value();
    }

    public void ValueUpdatedHandler(object sender, EventArgs e)
    {
        Update();
    }
}

现在,当您将接口的实现传递给组件时,组件将与实例交换委托,获取对其ValueGetter的引用并订阅其事件。然后IHaveAValueYouNeed的实现应该在值发生变化时(直接或因为会改变getter生成的计算值的某些内容发生变化)引发事件。这样,控制该值的对象可以告诉对该值感兴趣的人,它已经改变了。

答案 3 :(得分:1)

为什么不使用ToString?

public class GUIComponent
{
    object value = null;    // The value linked in
    string label = "";        // The label for the value
    string text = "";         // The label and value appended together

    public GUIComponent(string Text, object Value)
    {
        this.text = Text;
        this.value = Value;
    }

    public void Update()
    {
        this.text = this.label + this.value.ToString();
    }
}