簡體   English   中英

使用LINQ遞歸查找通用列表C#

[英]Recursive Lookup of generic List C# using LINQ

我有一個具有2個屬性的自定義類的通用列表。 這些屬性存儲形式和另一形式之間的關系。 該列表被構造為層次列表(父/子)關系。 我想要做的是基於父表單引用獲取所有表單的列表,該列表將傳遞給函數。 我認為最好的方法是使用遞歸方法的LINQ查詢。 我相信有人可以指出我正確的方向

這是列表中使用的類

class FormStack    {

    #region Declares

    private Form _form;
    private Form _parent;

    #endregion

    #region Constructor

    static FormStack()
    {
    }

    #endregion

    public Form Form
    {
        get { return _form; }
        set { _form = value; }
    }

    public Form Parent
    {
        get { return _parent; }
        set { _parent = value; }
    }

}

因此,我希望能夠調用一個方法並將一個表單引用傳遞給該函數,並獲取與此父級相關的所有子表單。

這是我一直在摸索的一些代碼

// create a lookup list
var list = formStack.ToLookup( p => object.ReferenceEquals( p.Parent, parent ) );

// create a function
Func<IEnumerable<Form>, IEnumerable<Form>> recurse = null;
recurse = qs =>
{
    return
        qs
            .Concat(
                from q in qs
                from q2 in recurse( list[] )
                select q2 );
};

// filter the list
var children = recurse( list[parent] ).ToList();

我有一個具有標准CRUD功能的Winform應用程序。 可以說有一個客戶列表,每個客戶可以有多個地址,這些地址中的每個地址都有多個建築物,我構造表單的方式是有一個客戶列表,您可以從此列表中打開詳細的表單特定客戶。 此表單在列表中包含客戶的詳細信息和所有地址。 此列表使用戶現在可以在列表中選擇一個地址,然后打開包含建築物列表的地址詳細信息表單,等等。...我的問題是我想關閉該客戶的客戶詳細信息和所有相關表單。 我的想法是保持表格之間的關系,但也許我有更好的方法?

好吧,聽起來像我有兩個問題。 一個是語法錯誤( recurse(list[])錯誤),另一個是您的FormStack並不是真正的堆棧。 它只有兩種形式,無法創建遞歸鏈。 我想你想要這個:

public class FormStack : IEnumerable<Form> // or just implement SelectMany
{    
    public Form Form { get; set; }
    public FormStack Parent { get; set; }  
    //implement IEnumerable<Form> or the SelectMany method
}

那么我想你可以做到這一點,但它似乎是一個尷尬的事:

Func<FormStack, IEnumerable<Form>> recurse = qs =>
{
    return from q in qs
           select (new[] { qs.Form }).Concat(recurse(qs.Parent));
};

var list = recurse(formStack).ToList();

那就是如果您堅持使用查詢語法。

但是,如果我是你,我會忘記所有這些,並實現一個IEnumerator<Form>為您完成所有操作:

public class FormStack : IEnumerable<Form> 
{    
    public Form Form { get; set; }
    public FormStack Parent { get; set; }  
    public IEnumerator IEnumerable:GetEnumerator() 
    { 
        return (IEnumerator)GetEnumerator();
    }
    public IEnumerator<Form> GetEnumerator() 
    { 
        return new FormStackEnumerator(this);
    }
}
public class FormStackEnumerator : IEnumerator<Form>
{
    private FormStack _stack;
    private FormStack _first;
    public Form Current { get { return _stack.Form; } }
    object IEnumerator.Current { get { return Current; } }

    public FormStackEnumerator(FormStack stack)
    {
        _stack = stack;
        _first = stack;
    }
    public bool MoveNext()
    {
        if (_stack.Parent == null)
        {
            return false;
        }
        _stack = _stack.Parent;
        return true;
    }
    public void Reset() { _stack = _first; }
    void IDisposable.Dispose() { }
}

然后,您需要在主代碼中執行的所有操作是:

var list = new List<Form>();
foreach (var node in formStack)
{
    list.Add(node.Form);
}

順便說一下,我只是查找了Form類(我不是WinForms開發人員),並且Forms本身有一個Parent成員。 因此,您實際上不需要將它們包裝在節點類型的構造中。 他們已經是節點了! 這使一切變得容易:

var list = new List<Form>();

Action<Control> recurse = target =>
{
    var form = target as Form;
    if (form != null)
    {
        list.Add(form);
        recurse(target.Parent);
    }
}

這是我組成的:

為所有表單創建一個基本表單:

 public class MyFormBase : Form { public MyFormBase() { FormRepository.RegisterForm(this); } public MyFormBase(MyFormBase parent) : this() { Parent = parent; } public MyFormBase Parent { get; set; } } 

每個表單只能在構造函數中傳遞一個父級。

創建一個存儲庫(或類似的東西)來存儲您的表單->我不想在表單本身中存儲所有子級

//infrastructure - simulated with a static class
public static class FormRepository
{
    private static List<MyFormBase> _allForms = new List<MyFormBase>();

    public static void RegisterForm(MyFormBase form)
    {
        _allForms.Add(form);
    }

    public static void CloseFormAndChildren(MyFormBase form)
    {
        _allForms.Where(x => x.Parent.Equals(form)).ToList().ForEach(x => CloseFormAndChildren(x));
        form.Close();
    }
}

以您要關閉的任何形式(包括子項)調用CloseFormAndChildren。 這可以在結束事件中調用...

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM