views:

133

answers:

4

Hi,

I have an interface named IHarvester.

There are 3 implementations of that interface, each under their own namespace:

  1. Google
  2. Yahoo
  3. Bing

A HarvesterManager uses the given harvester. It knows the interface and all 3 implementations.

I want some way of letting the class user say in which harvester it wants to use. And in the code select that implementation, without a switch-case implementation.

Can reflection save my day?

Here is the code bits:

// repeat for each harvester
namespace Harvester.Google
{
    public abstract class Fetcher : BaseHarvester, IInfoHarvester {...}
}


public enum HarvestingSource
{
    Google,
    Yahoo,
    Bing,
}
class HarvesterManager {
    public HarvestingSource PreferedSource {get;set;}
    public HarvestSomthing()
    {
        switch (PreferedSource) .... // awful...
    }
}

Thanks.


I will give my 2 cents of why I want to change this. There several people writing harvesters, I want them to focus only on building more harvesters, without ever needing to update the enum, or at worst, update only the enum.

+1  A: 

Since they're all inheriting from a common interface, you can use Activator to create an instance of an object using that interface, but all that will be available to you would be the specific properties and methods of the interface. Something like the below.

using System;
using Demo;

namespace Demo
{
    class Program
    {
        static void Main(string[] args)
        {
            Type type = Type.GetType("Harvester.Google.GoogleHarvester");
            IHarvester harvester = (IHarvester)Activator.CreateInstance(type);

            Console.WriteLine(harvester.Blah);
            Console.Read();
        }
    }

    public interface IHarvester
    {
        string Blah { get; }
    }
}

namespace Harvester.Google
{
    public class GoogleHarvester : IHarvester
    {
        #region IHarvester Members

        public string Blah
        {
            get
            {
                return "Google";
            }
        }

        #endregion
    }
}

namespace Harvester.Yahoo
{
    public class YahooHarvester : IHarvester 
    {
        #region IHarvester Members

        public string Blah
        {
            get { return "Yahoo"; }
        }

        #endregion
    }
}

namespace Harvester.Bing
{
    public class BingHarvester : IHarvester 
    {
        #region IHarvester Members

        public string Blah
        {
            get { return "Bing"; }
        }

        #endregion
    }
}
Anthony Pegram
+2  A: 

I think you should look on dependency injection. You could use exising IoC containers instead of inventing your own one, e.g. you could use Unity. Here is an article on how you could use Unity.

Andrew Bezzub
+1  A: 

I think you would get more milage from a Strategy Pattern implemenation.

Sky Sanders
Interesting....
Am
A: 

If you have a fixed set of options to choose from I'd go for the factory class:

internal static class HarvestorFactory
{
    private static Dictionary<HarvestingSource, IHarvester> harvesters = 
        new Dictionary<HarvestingSource, IHarvester>
        {
            { HarvestingSource.Google, new GoogleHarvester() },
            { HarvestingSource.Yahoo, new YahooHarvester() },
            { HarvestingSource.Bing, new BingHarvester() },
        };

    internal static IHarvester Get( HarvestingSource source )
    {
        return harvesters[ source ];
    }
}

This gives you freedom to control whether instances should be singletons (as in the example above), per-caller or some other option that fits the scenario in which the code is used.

Morten Mertner