0

Assume I have a class A that has a private List Plist and the functions necessary for basic interaction with it (adding, deleting etc). In my class B, I use these functions, but also want to iterate/search/whatever over it via LINQ in many different ways. Creating a new function for every query seems unreasonable, so I wonder if I could create a function that takes a query as an argument and applies it to the private list. I am aware that it pretty much defeats the point of having the list private in the first place, however Im wondering if it's possible

Technically, I would like it to work like this (which it obviously doesnt, but you get the idea):

public class A
{
    private List<C> Plist { get; set; } = new List<C>();


    public C Search(string query)
    {
        this.Plist.query
    }
}

public class B
{
    A a = new A();

    a.Search("Where(i => i.AnotherListInC.Contains(SomeObject))");
}

Is there a way to access a private property with complex LINQ queries, or more generally, concatenate a string to existing code to create new code?

Sven Engling
  • 39
  • 1
  • 7
  • 1
    Could you implement `IEnumerable` for `A`? Then you can simply call `Where` directly. Or do you want to pass a string? – Lee Jan 04 '19 at 10:37
  • I think Lee's suggestion is good, but let's just assume that you could do what you are asking you would turn compile-time errors into run-time errors which is generally not a great thing. – Brian Rasmussen Jan 04 '19 at 10:39
  • I haven't worked directly with that Interface yet, so I don't know. Im going to look into it, thanks for the hint. However I'm also interested in the stringified-code-as-parameter approach since it's probably very useful for other things. – Sven Engling Jan 04 '19 at 10:40
  • 1
    May be you should use `IReadOnlyCollection` and expose list through it? – JohnyL Jan 04 '19 at 10:41
  • Is passing such queries by string a necessity? If not I'll suggest passing Predicate [link](https://learn.microsoft.com/pl-pl/dotnet/api/system.predicate-1?view=netframework-4.7.2) as a parameter. Then in Your Search method You gan filter for all elements meeting diven predicate – Krzysiek Przekwas Jan 04 '19 at 10:43
  • @SvenEngling - I think you might be looking for something like this for string to LINQ https://stackoverflow.com/q/821365/3645638 – Svek Jan 04 '19 at 10:46

1 Answers1

4

If you need to use String as parameter it will be hard as you would have to emit code. If you just want to search private list than create method that accepts predicate as parameter:

public class A
{
    private List<C> Plist { get; set; } = new List<C>();
    public IEnumerable<C> Search(Func<C, bool> predicate)
    {
        return this.Plist.Where(predicate);
    }
}

public class B
{
    public void SomeMethod()
    {
        A a = new A();
        a.Search(i => i.AnotherListInC.Contains(SomeObject));
    }
}

Similar method can be written for any Linq method. Just create method that accepts the same parameters as Linq method except of first parameter (IEnumerable<TSource>).

In case you want all Linq methods available you can implement IEnumerable<C> on your class A

public class A : IEnumerable<C>
{
    private List<C> Plist { get; set; } = new List<C>();

    public IEnumerator<C> GetEnumerator()
    {
        return ((IEnumerable<C>)Plist).GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return ((IEnumerable<C>)Plist).GetEnumerator();
    }
}

public class B
{
    public void SomeMethod()
    {
        A a = new A();
        a.Where(i => i.AnotherListInC.Contains(SomeObject));
        a.Any(i => i.AnotherListInC.Contains(SomeObject));
    }
}
Pablo notPicasso
  • 3,031
  • 3
  • 17
  • 22
  • These looks very well. Func is event better than my Predicate proposed above – Krzysiek Przekwas Jan 04 '19 at 10:46
  • This looks very much like the thing I'm looking for, thank you very much. Another question however is, what if I dont want to use Where, but for example Any. Is there a way to omit the Where from Search and deliver it with SomeMethod, or would I have to create a new function for each? – Sven Engling Jan 04 '19 at 10:48