Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I have this Food class with 20 properties. I need to use this Food class and output 3 different files, using variations of these 20 fields. For example, File 1 contains output only 8 fields. File 2 contains 15 fields. File 3 contains 18 fields.

So right now, I have these 3 separate methods.

    FoodService()
    {
        void WriteRecommendedFood(IList<Food> foodList);
        void WriteRecommendedFoodCalculation(IList<Food> foodList);
        void WriteRecommendedFoodAllEligibleFoods(IList<Food> foodList);
    }

So I'd write:

    public void WriteRecommendedFood(IList<Food> foodList)
    {
            using (StreamWriter sw = new StreamWriter("file.csv", false)
            {
                    StringBuilder sb = new StringBuilder();
                    foreach (Food f in foodList)
                    {
                            sb.Append(f.Field1); 
                            //Repeat for the # of fields I want to spit out
                            sb.Clear();
                            sw.WriteLIne(sb.ToString());
                    }
                    sw.Close();
            }
    }

I feel like I'm writing the same code three times (with slight variations). I started to read up on different design patterns like Visitor and Strategy pattern, but I'm not sure which design pattern to improve my code. (Note: I only need to output it to a comma delimited file at this time. Also, from the UI side, the user gets to select which one they want to output (either one to all 3 files.) Any suggestions?

share|improve this question

2 Answers 2

It seems that the only thing that changes between these three functions is a list of fields that get written. There are several ways you can represent "a field" (and thus a list of fields) in a program; one of the most convenient is doing so as a function that extracts this field's value from a Food instance.

The type of this representation would be Func<Food, object>, so with a List<Func<Food, object>> you are good to go.

public void WriteFoodData(IEnumerable<Food> foodList, IEnumerable<Func<Food, object>> valueProviders)
{
    using (StreamWriter sw = new StreamWriter("file.csv", false))
    {
        StringBuilder sb = new StringBuilder();
        foreach (Food f in foodList)
        {
            foreach (var provider in valueProviders)
            {
                sb.Append(provider(f).ToString());
            }
            sw.WriteLIne(sb.ToString());
            sb.Clear();
        }
    }
}

Now you can create a "list of fields" and use it to call this method:

var valueProviders = new List<Func<Food, object>>
{
    f => f.Field1,
    f => f.Field4,
    // etc
};

var foods = /* whatever */
WriteFoodData(foods, valueProviders);
share|improve this answer

I would remove the responsibility for formatting from your FoodService and inject it instead.

    public class FoodService()
    {
        public void WriteRecommendedFood(IList<Food> foodList, IFoodFormatter formatter)
        {
            using (StreamWriter sw = new StreamWriter("file.csv", false)
            {
                StringBuilder sb = new StringBuilder();
                foreach (Food f in foodList)
                {
                   sw.WriteLine(foodformatter.Format(f));
                }
                sw.Close();
            }
        }
    }

    interface IFoodFormatter
    {
        string Format(Food f);
    }

This whay you can create concrete formatters like CalculationFormatter and ElligableFoodsFormatter.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.