不知道 T 的情况下如何保留 List<T> 的引用?

3
澄清: 目标是使我的UIPList能够观察任何T为iUIP或其子类的ObservableList,并且UIPrefab按钮连接到列表中的,同时还能随时更改它正在观察的列表(并且仅观察一个列表)。

我可以画出GUI按钮并使用下面的hacky代码使其第一次观察成功,但没有办法将引用存储在UIPList中,以便我可以在想要观看其他内容时取消订阅。如果将其转换为“UIPList”(这将使存储引用成为可能),则会失去上述第三个功能。

现在我正在尝试由菜单(了解所涉及的UIPListsObservableLists)负责在内容更改时取消订阅,但理想情况下,我只需将ObservableList传递给UIPList,它就能知道如何监视它、绘制GUI并在自己获得新列表时取消订阅。

原帖:我有一个UIPList,它应该观察一个ObservableList<T> where T:iUIP。(iUIP指一个具有可以在UIPList中绘制按钮的类)。

问题是我不能存储对列表的本地引用,因为它可以是ObservableList<iUIP>或者ObservableList<Character>ObservableList<Organization>等(其他继承类)。

我不能使用ObservableList<iUIP>作为对UIPList的引用,因为我可能想要观察一个无法强制转换为ObservableList<iUIP>的列表,尽管角色是从继承而来的,因此没有办法存储对UIPList应该观察的列表的本地引用。

我在UIPList上使用了一个SetWatchList<T>(ObservableList<T> list)方法来接收待观察的列表,但由于没有对原始列表的引用,当我想要更改UIPList正在看的内容时,我就没有所需的引用来取消订阅以前的列表。

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
//using System.Collections.ObjectModel;

public class UIPList : MonoBehaviour
{
public GUIManager GUIManager;
public UILabel Title;
public UITable Contents;

//  ObservableList<T>.ListChangedEventHandler subscribedChangeEvent;

public void WatchList<T>(ObservableList<T> list) where T: iUIP
{
    this.subscribedChangeEvent = list.ListChanged;
    list.ListChanged += DrawUIPList;//TODO make always clear prev?
    DrawUIPList<T>(list);
}

//dont have a reference to the old list to know what to stop watching!
//  public void StopWatchList<T>(ObservableList<T> list) where T: iUIP
//  {
//      list.ListChanged -= DrawUIPList;
//  }

// Use this for initialization
protected void Start()
{
    this.GUIManager = GUIManager.Find;
}
// Update is called once per frame
void Update()
{
}


void DrawUIPList<T>(object source, ObservableList<T>.ListChangedEventArgs e) where T : iUIP
{
    DrawUIPList<T>(e.list);
}
void DrawUIPList<T>(ObservableList<T> list) where T:iUIP
{
    //todo AddComponentMenu/RemoveItem/adjut ReadOnlyCollectionBase changed UIPs
    ClearContents();
    this.Contents.Reposition();
    foreach (T uip in list)//TODO make this automatic, not need each one
    {
        //          Debug.Log("Adding UIP:" + child.name);
        if (uip.UIPButton is UIPCorporationButton)
            UIPCorporationButton.Create(this.Contents.gameObject, (uip as Corporation));

        if (uip.UIPButton is UIPCompanyButton)
            UIPCompanyButton.Create(this.Contents.gameObject, (uip as Company));

        if (uip.UIPButton is UIPAssetButton)
            UIPAssetButton.Create(this.Contents.gameObject, (uip as Asset));

        if (uip.UIPButton is UIPIndButton)
            UIPIndButton.Create(this.Contents.gameObject, (uip as Industry));

        if (uip.UIPButton is UIPSecButton)
            UIPSecButton.Create(this.Contents.gameObject, (uip as Sector));

        if (uip.UIPButton is UIPOperativeButton)
            UIPOperativeButton.Create(this.Contents.gameObject, (uip as Operative));

        if (uip.UIPButton is UIPAgencyButton)
            UIPAgencyButton.Create(this.Contents.gameObject, (uip as Agency));

        if (uip.UIPButton is UIPBrokerButton)
            UIPBrokerButton.Create(this.Contents.gameObject, (uip as Broker));

        if (uip.UIPButton is UIPCellButton)
            UIPCellButton.Create(this.Contents.gameObject, (uip as Cell));

        if (uip.UIPButton is UIPMissionButton)
            UIPMissionButton.Create(this.Contents.gameObject, (uip as Mission));

        if (uip.UIPButton is UIPObjectiveButton)
            UIPObjectiveButton.Create(this.Contents.gameObject, (uip as Objective));

        if (uip.UIPButton is UIPChallengeButton)
            UIPChallengeButton.Create(this.Contents.gameObject, (uip as Challenge));


    }
    //this.Contents.Reposition();
    this.Contents.repositionNow = true;
}

public void ClearContents()
{
//      this.Contents.children.children.Clear();
    int count = this.Contents.transform.childCount;     
    for (int i = count - 1; i >= 0; i--)
    {           
        GameObject.Destroy(this.Contents.transform.GetChild(i).gameObject);         
    }
}
}

尽管该字符从iUIP继承,但无法转换为ObservableList<iUIP>,这怎么可能呢? - Robert Levy
基本上,虽然 Character 可以保存在 iUIP 引用中,但你不能使用 List<T> 做同样的事情。从技术上讲,我可以将 list<Character> 中的每个对象放入一个新的 list<iUIP> 中,但那是一个新的列表,不会反映出正在观察的列表发生的变化。 - LZG
1个回答

2

将整个类泛型化

public class UIPList<T> : MonoBehaviour where T : iUIP

然后您可以存储对列表的引用。这样更好地封装了列表的实际含义。

不要忘记从您的方法中删除通用约束。

public void WatchList(ObservableList<T> list)

这将取消UIPList观看任何类型的列表的能力,因此我不能再像活动菜单所需的那样从<iUIP>更改观察列表到<character>或<organization>等。每次它们的内容更改为不同类型时,我都必须销毁并重新制作UIPLists。 主要问题似乎在于我可以使用iUIP引用来保存Character或Organization的地方,list<iUIP>无法保存list<Character>或list<Organization>... - LZG
刚刚意识到Unity不会在检查器中显示UIPList<T>,这意味着从菜单到实际GUI元素的引用已经失效了。 - LZG
“每次 UIPLists 内容更改为不同类型时,我都需要销毁并重新创建它们” - 这听起来像是一个合理的行为。 - BlueRaja - Danny Pflughoeft

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接