Multiple OfType Linq?

本文关键字:Linq OfType Multiple | 更新日期: 2023-09-27 18:04:19

我有一个linq查询,选择占位符中的所有文本框,并使用结构体将它们添加到列表中。我需要扩展这个功能,也采取DropDownList的selectedvalue,我很确定我做错了,因为当我调试的方法列表计数是0。

我自己的猜测是声明2 OfType<>()是错误的,但我对linq很陌生,我不知道还能怎么做。

任何帮助都太棒了!提前谢谢。

到目前为止我写的是:

public struct content
{
    public string name;
    public string memberNo;
    public int points;
    public string carclass;
}
List<content> rows = new List<content>();
protected void LinkButton_Submit_Attendees_Click(object sender, EventArgs e)
{
List<content> rows = PlaceHolder_ForEntries.Controls.OfType<TextBox>().OfType<DropDownList>()
        .Select(txt => new
        {
            Txt = txt,
            Number = new String(txt.ID.SkipWhile(c => !Char.IsDigit(c)).ToArray())
        })
        .GroupBy(x => x.Number)
        .Select(g => new content
        {
            carclass = g.First(x => x.Txt.ID.StartsWith("DropDownlist_CarClass")).Txt.SelectedValue,
            name = g.First(x => x.Txt.ID.StartsWith("TextBox_Name")).Txt.Text,
            memberNo = g.First(x => x.Txt.ID.StartsWith("TextBox_MemberNo")).Txt.Text,
            points = int.Parse(g.First(x => x.Txt.ID.StartsWith("TextBox_Points")).Txt.Text)
        })
        .ToList();
}

这是创建控件的方法。

protected void createcontrols()
{
    int count = 0;
    if (ViewState["count"] != null)
    {
        count = (int)ViewState["count"];
    }
    while (PlaceHolder_ForEntries.Controls.Count < count)
    {
        TextBox TextBox_Name = new TextBox();
        TextBox TextBox_MemberNo = new TextBox();
        TextBox TextBox_Points = new TextBox();
        DropDownList DropDownList_CarClass = new DropDownList();
        DropDownList_CarClass.Items.Add("Car1");
        ...
        DropDownList_CarClass.Items.Add("Car2");
        TextBox_Name.Attributes.Add("placeholder", "Navn");
        TextBox_Name.ID = "TextBox_Name" + PlaceHolder_ForEntries.Controls.Count.ToString();
        TextBox_Name.CssClass = "input-small";
        TextBox_MemberNo.Attributes.Add("placeholder", "Medlemsnr.");
        TextBox_MemberNo.ID = "TextBox_MemberNo" + PlaceHolder_ForEntries.Controls.Count.ToString();
        TextBox_MemberNo.CssClass = "input-small";
        TextBox_Points.Attributes.Add("placeholder", "Point");
        TextBox_Points.ID = "TextBox_Points" + PlaceHolder_ForEntries.Controls.Count.ToString();
        TextBox_Points.CssClass = "input-small";
        PlaceHolder_ForEntries.Controls.Add(TextBox_Name);
        PlaceHolder_ForEntries.Controls.Add(TextBox_MemberNo);
        PlaceHolder_ForEntries.Controls.Add(DropDownList_CarClass);
        PlaceHolder_ForEntries.Controls.Add(TextBox_Points);
        PlaceHolder_ForEntries.Controls.Add(new LiteralControl("<br />"));
    }
}

Multiple OfType Linq?

您可以使用Where并检查对象is的实例是否为!

List<content> rows = PlaceHolder_ForEntries.Controls.Cast<Control>().Where(c => c is TextBox || c is DropDownList)
        .Select(txt => new
        {
            Txt = txt,
            Number = new String(txt.ID.SkipWhile(c => !Char.IsDigit(c)).ToArray())
        })
        .GroupBy(x => x.Number)
        .Select(g => new content
        {
            carclass = g.First(x => x.Txt.ID.StartsWith("DropDownlist_CarClass")).Txt.SelectedValue,
            name = g.First(x => x.Txt.ID.StartsWith("TextBox_Name")).Txt.Text,
            memberNo = g.First(x => x.Txt.ID.StartsWith("TextBox_MemberNo")).Txt.Text,
            points = int.Parse(g.First(x => x.Txt.ID.StartsWith("TextBox_Points")).Txt.Text)
        })
        .ToList();

AppDeveloper是对的。OfType<T>过滤除T以外的所有类型的对象;因此,通过过滤两次,您可以有效地消除列表中的所有对象。

如果您想将这个逻辑(从列表中过滤除以外的所有类型)包装成可重用的东西,那么没有什么可以阻止您实现自己的扩展方法:

using System.Collections;
public static class EnumerableExtensions
{
    public static IEnumerable OfType<T1, T2>(this IEnumerable source)
    {
        foreach (object item in source)
        {
            if (item is T1 || item is T2)
            {
                yield return item;
            }
        }
    }
}

在项目中包含上述类将允许您在应用程序中编写这样的代码:

var textBoxesAndDropDowns = controls.OfType<TextBox, DropDownList>();

要了解有关扩展方法的更多信息,请参阅MSDN关于该主题的文章。

请注意,由于上面的扩展方法"允许"两种不同的类型,因此结果仍然是一个非泛型IEnumerable序列。如果您想将结果视为通用序列(例如,IEnumerable<Control>),我建议使用Cast<T>扩展方法:

var filteredControls = controls.OfType<TextBox, DropDownList>().Cast<Control>();

我还没有完全阅读这个问题,但是从标题的含义来看,你可以实现以下行为:

var collection = new object[] { 5, "4545",  'd', 54.5 , 576 };
var allowedTypes = new[] { typeof(string), typeof(int) }; 
var result = collection
 .Where(item => allowedTypes.Contains(item.GetType()));

取@Shimmys对扩展方法的回答:

/// <param name="wantedTypes">--- Sample: --- new Type[] { typeof(Label), typeof(Button) }</param>
public static IEnumerable OfTypes(this IEnumerable collection, Type[] wantedTypes)
{
    if (wantedTypes == null)
        return null;
    else
        return collection.Cast<object>().Where(element => wantedTypes.Contains(element.GetType()));
}

用法:

// List of 3 different controls
List<object> controls = new List<object>(new object[] { new Label(), new Button(), new TextBox() });
// Get all labels and buttons
var labelsAndButtons = controls.OfTypes(new Type[] { typeof(Label), typeof(Button) });

你的问题是在OfType<>().OfType<>()中,你用不同的类型过滤了两次