以类似Rails的方式链接C#LINQ

时间:2016-03-27 11:57:06

标签: c# linq

我有以下类来存储一些静态数据。我还有几种使用LINQ过滤数据的方法。像这样:

static class Data {

    // ...

    static public Weapon[] weapons = new Weapon[] {
        // ...
    }

    static public GetUnlockedWeapons() {
        Data.weapons.Where( a => a.unlocked ).ToArray();
    }

    static public GetWeaponsType(string type) {
        Data.weapons.Where( a => a.type == type ).ToArray();
    }

// ...
}

但现在我看到这种方式不是很灵活。当我构建更多过滤器时,将它们组合起来非常困难和/或冗长。

我来自Ruby on Rails开发,其中ActiveRecord具有可链接的scopes

我想知道我是否有某种方式可以chain我的过滤器,方式与此相似:

weapons = Data.weapons.unlocked().type("sword").andMore().andEvenMore();

3 个答案:

答案 0 :(得分:3)

是的,你可以这样做:

static class Data {

    // ...

    static public Weapon[] weapons = new Weapon[] {
        // ...
    }

    public static IEnumerable<Weapon> GetUnlockedWeapons(this IEnumerable<Weapon> weapons) {
        return weapons.Where( a => a.unlocked );
    }

    public static IEnumerable<Weapon> GetWeaponsType(this IEnumerable<Weapon> weapons, string type) {
        return weapons.Where( a => a.type == type );
    }

// ...
}

使用它:

var weapons = Data.weapons.GetUnlockedWeapons().GetWeaponsType("pistol").AndMore().ToList();

没有必要返回一个数组,因为它可能会链接它。将集合的具体化保留给调用者(在这种情况下,我们使用ToList

答案 1 :(得分:2)

如何将过滤器定义为extension methodsIEnumerable<Weapon>类型:

public static class Data 
{
    public Weapon[] GetUnlockedWeapons(this IEnumerable<Weapon> weapons)
    {
        return weapons.Where( a => a.unlocked ).ToArray();
    }

    public static Weapon[] GetWeaponsType(this IEnumerable<Weapon> weapons, string type)
    {
        return weapons.Where( a => a.type == type ).ToArray();
    }
}

现在假设您有一个武器列表,您可以将这些过滤器应用于它:

Weapon[] weapons = new Weapon[] 
{
    // ...
};

weapons = weapons.unlocked().type("sword").andMore().andEvenMore();

或者,您可以定义使用所谓的流畅接口的API:

public class Data 
{
    public Data(Weapon[] weapons)
    {
        this.Weapons = weapons;
    }

    public Weapon[] weapons { get; private set; }

    public Data GetUnlockedWeapons()
    {
        return new Data(this.Weapons.Where( a => a.unlocked ).ToArray());
    }

    public Data GetWeaponsType(this IEnumerable<Weapon> weapons, string type) 
    {
        return new Data(this.Weapons.Where( a => a.type == type ).ToArray());
    }
}

然后像这样使用:

Weapon[] weapons = new Weapon[] 
{
    // ...
};

weapons = new Data(weapons).unlocked().type("sword").andMore().andEvenMore().Weapons;

答案 2 :(得分:1)

    public static class WeaponFilters
    {
         public static Weapon[] GetUnlocked(this Weapon[] w)
        {
             return w.Where(x=> x.unlocked).ToArray();
        }
         public static Weapon[] Type(this Weapon[] w, string type)
        {
             return w.Where(x=> x.type == type).ToArray();
        }
   //some more filters...
    }

然后您可以像:

一样使用它
weapons = weapons.unlocked().type("sword");