Можно ли обобщить / абстрагировать / реорганизовать разницу в пространстве имен между реализациями? - PullRequest
0 голосов
/ 18 мая 2011

Ниже представлены три реализации интерфейса.Единственная разница между реализацией 1 и реализацией 2 заключается в пространстве имен, содержащем ItemWrapper.Можно ли это реорганизовать, используя обобщение или что-то еще?

interface IItemProvider {
    object GetItem(Item item);
}

//1
class SomeNamespaceProvider : IItemProvider {
    object GetItem(Item item) {
        return SomeNamespace.ItemWrapper.GetItem(item);
    }
}

//2
class OtherNamespaceProvider : IItemProvider {
    object GetItem(Item item) {
        return OtherNamespace.ItemWrapper.GetItem(item);
    }
}

//3
class TotallyDifferentProvider : IItemProvider {
    object GetItem(Item item) {
        return DifferentItemRetriever(item);
    }
}

Ответы [ 2 ]

1 голос
/ 18 мая 2011

Вот один из способов:

abstract class ItemWrapper {
    public abstract object GetItem(Item item);
}

class OtherNamespaceItemWrapper : ItemWrapper {
    public override object GetItem(Item item) {
        return OtherNamespace.ItemWrapper.GetItem(item);
    }
}

class SomeNamespaceItemWrapper : ItemWrapper {
    public override object GetItem(Item item) {
        return SomeNamespace.ItemWrapper.GetItem(item);
    }
}

Тогда:

class NamespaceProvider<T> where T : ItemWrapper, new() {
    private readonly ItemWrapper itemWrapper;
    public NamespaceProvider() {
        this.itemWrapper = new T();
    }

    public object GetItem(Item item) {
        return this.GetItem(item);
    }
}

И

class SomeNamespaceProvider : NamespaceProvider<SomeNamespaceItemWrapper> { }
class OtherNamespaceProvider : NamespaceProvider<OtherNamespaceItemWrapper> { }
1 голос
/ 18 мая 2011

Из вашего описания я понимаю, что у вас есть статические методы в классах SomeNamespace.ItemWrapper и OtherNamespace.ItemWrapper, и они не реализуют интерфейс IItemProvider. Вы хотите превратить эти статические методы в методы экземпляра, и вы не знаете, как это сделать.

Если классы SomeNamespace.ItemWrapper и OtherNamespace.ItemWrapper не являются статичными, вы можете явно реализовать IItemProvider:

namespace SomeNamespace
{
    public class ItemWrapper: IItemProvider
    {
        public static object GetItem(TaskRunProcessor.Test.Item item)
        {
            return null;
        }

        object IItemProvider.GetItem(Item item)
        {
            return ItemWrapper.GetItem(item);
        }
    }
}

Если они должны оставаться статичными или по какой-либо причине у вас нет доступа к коду, я бы порекомендовал какой-то функциональный подход:

public class GenericProvider : IItemProvider
{
    private Func<Item, object> m_Retriever;

    public GenericProvider(Func<Item,object> retriever)
    {
        if (retriever == null) throw new ArgumentNullException("retriever");
        m_Retriever = retriever;
    }
    object GetItem(Item item)
    {
        return m_Retriever(item);
    }
}

Тогда вы сможете использовать `GenericItemProvider 'следующим образом:

public class ItemProvderClient
{
    public void Use()
    {
        IItemProvider provider1 = new GenericProvider(SomeNamespace.ItemWrapper.GetItem);
        IItemProvider provider2 = new GenericProvider(OtherNamespace.ItemWrapper.GetItem);

        provider1.GetItem(null);
        provider2.GetItem(null);
    }
}

В обоих решениях нет необходимости создавать больше классов для пространства имен evey, таких как SomeNamespaceProvider класс, который у вас был на первом месте.

...