Альтернатива отражения для включения enum для выбора пространства имен / класса - PullRequest
1 голос
/ 21 марта 2010

У меня есть интерфейс с именем IHarvester.

Существует 3 реализации этого интерфейса, каждая в своем собственном пространстве имен:

  1. Google
  2. Yahoo
  3. Bing

HarvesterManager использует данный комбайн. Он знает интерфейс и все 3 реализации.

Я хочу, чтобы какой-нибудь классный пользователь сказал, какой харвестер он хочет использовать. И в коде выберите эту реализацию, без реализации переключателя.

Может ли рефлексия спасти мой день?

Вот биты кода:

// 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...
    }
}

Спасибо.


Я дам свои 2 цента, почему я хочу это изменить. Несколько человек пишут комбайны, я хочу, чтобы они сосредоточились только на создании большего количества комбайнов, без необходимости обновлять перечисление или, в худшем случае, обновлять только перечисление.

Ответы [ 4 ]

2 голосов
/ 21 марта 2010

Я думаю, вы должны посмотреть на внедрение зависимости . Вы можете использовать существующие контейнеры IoC вместо того, чтобы изобретать свой собственный, например, Вы можете использовать Unity . Здесь - статья о том, как вы можете использовать Unity.

1 голос
/ 21 марта 2010

Я думаю, вы получите больше прибыли от реализации Strategy Pattern .

1 голос
/ 21 марта 2010

Поскольку все они наследуются от общего интерфейса, вы можете использовать Activator для создания экземпляра объекта с использованием этого интерфейса, но все, что вам будет доступно, - это конкретные свойства и методы интерфейса. Нечто подобное ниже.

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
    }
}
0 голосов
/ 22 марта 2010

Если у вас есть фиксированный набор опций на выбор, я бы пошел на заводской класс:

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 ];
    }
}

Это дает вам свободу контролировать, должны ли экземпляры быть одиночными (как в примере выше), для каждого вызывающего абонента или какой-либо другой опцией, которая соответствует сценарию, в котором используется код.

...