1

I have a string

string partialCityName

and a generic list .

var city = List<City>

I want to do two things:

1. Filter the list based on the name and I am doing that like this:

var availableCities = cityList.Where(f => f.CityName.StartsWith(partialCityName));

2. Get a list of chars based on the above var "availableCities" and I am doing that like this.

var nextAvailableCharacters = avalibleCities .
          Where(s => s.CityName.Length > partialCityName.Length).
          Select(s => s.CityName.Substring(partialCityName.Length)[0]).ToList();

Currently this is happening in one method, and is working. However I am trying to understand design patterns, and am trying to implement the Strategy pattern.

So the first question is, is this the correct pattern to use? If so how?

This is what I have got so far.

public interface IFilterStrategy
{
   List<T> Filter<T>(List<T> filterThisData, string filter);
}

Then:

    public class FilterCityStrategy : IFilterStrategy
    {

        public List<City> Filter<City>(List<City> filterThisData, string partialCityName)
        {
            //Fails to compile cityName not member of f 
            return filterThisData.Where(f => f.CityName.StartsWith(partialCityName));
        }
    }
Ayo Adesina
  • 2,231
  • 3
  • 37
  • 71

2 Answers2

3

Firstly, you declare your interface like this :

public interface IFilterStrategy<T>
{
    List<T> Filter(List<T> filterThisData, string filter);
}

And then you need to inherit from a type-specific instantiation of this interface :

public class FilterCityStrategy : IFilterStrategy<City>
{
    public List<City> Filter(List<City> filterThisData, string partialCityName)
    {
      return filterThisData.Where(f => f.CityName.StartsWith(partialCityName)).ToList<City>();
    }
}

See https://repl.it/repls/UnluckyEqualRaptors

The error you were getting was because the Filter method was declared as a template method with template parameter City. This means that City acts as an arbitrary type in this function definition and therefore shadows/masks the declaration of your City class elsewhere in your code :

    public List<City> Filter***<City>***(List<City> filterThisData, string partialCityName)
    {
        //Fails to compile cityName not member of f 
        return filterThisData.Where(f => f.CityName.StartsWith(partialCityName));
    } 
the4thamigo_uk
  • 835
  • 4
  • 8
0

You could extend it a little bit to accommodate bit more complicated filtering. For example if you have a country filter and a city filter, chances are city filter will have a country code as well.

interface IFilter
{
}

class CountryFilter 
{
    string PartialCountryName { get; set;}
}

class CityFilter 
{
    string CountryCode { get; set;}
    string PartialCityName { get; set;}
}



interface IFilterStrategy<T,U> where U:IFilter
{
    List<T> Filter(List<T> source,U filter);
}

class CountryFilterStategy : IFilterStrategy<Country,CountryFilter>
{
    List<Country> Filter(List<Country> source,CountryFilter filter)
    {
        //logic
    }
}


class CityFilterStategy : IFilterStrategy<City,CityFilter>
{
    List<City> Filter(List<City> source,CityFilter filter)
    {
        //logic
    }
}
Low Flying Pelican
  • 5,974
  • 1
  • 32
  • 43