Применить ограничение к классу, придерживаться интерфейса - PullRequest
0 голосов
/ 15 ноября 2018

У меня есть требование, чтобы иметь возможность выполнять много преобразований внешних моделей в мои собственные внутренние модели.

Я решил применить шаблон адаптера, но я хочу сделать его как можно более универсальным. Поэтому я хочу, чтобы он обрабатывал оба «одиночных» POCO, но если мне нужно передать / адаптировать коллекцию, это также должно сработать, например:

IEnumerable<IAdaptee> OR IList<TAdaptee>

и вернуть мои собственные адаптированные объекты:

IEnumerable<IAdapted> OR IList<TAdapted>

Я хочу сделать что-то вроде следующего:

public interface IGenericAdapter
{
    TAdapted Adapt<TAdapted,TAdaptee>(TAdaptee adaptee);
}

Когда я отклеиваюсь, когда я создаю свой класс «Адаптер», а затем реализую описанный выше интерфейс, я получаю ошибки несоответствия ограничений. Это, конечно, имеет смысл, потому что если я применяю ограничения к классам, которые реализуют интерфейс, а у интерфейса их нет, то, конечно, возникают ошибки.

Итак:

public class AToBAdapter
{
public TAdapted Adapt<TAdapted,TAdaptee>(TAdaptee adaptee)
where TAdapted: IList<FooAdapted>
where TAdaptee: IList<FooAdaptee>
{
// I want my constraints to be active here, as I need to perform specific operations here
}
}

Вышесказанное прекрасно работает само по себе, что хорошо. Но я хочу спрятать все это за общим интерфейсом, который я могу использовать в любое время.

Конечно, как только я добавлю это, произойдет сбой из-за отсутствия ограничений на интерфейс, но ограничений на реализующий класс.

public class AToBAdapter:IAdapterGeneric

Какая здесь волшебная пуля, которая позволит мне создать действительно универсальный Адаптер - я предполагаю определенные ограничения интерфейса? Кастинг? но нужна помощь для лучшего курса действий.

Спасибо, Чудь

Ответы [ 2 ]

0 голосов
/ 15 ноября 2018

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

public interface IAdaptee { }
public interface IAdapted { }

И используйте эти интерфейсы в качестве ограничений интерфейса вашего адаптера:

public interface IGenericAdapter<out TAdapted, in TAdaptee>
    where TAdaptee : IAdaptee
    where TAdapted : IAdapted
{
    TAdapted Adapt(TAdaptee adaptee);
}

Вы можете передать этот адаптер вспомогательному методу для адаптации нескольких объектов (при условии, что логика адаптации останется неизменной для нескольких):

public IEnumerable<TAdapted> AdaptMultiple<TAdapted, TAdaptee>
    (IEnumerable<TAdaptee> adaptees, IGenericAdapter<TAdapted, TAdaptee> adapter)
    where TAdaptee : IAdaptee
    where TAdapted : IAdapted
{
    return adaptees.Select(adapter.Adapt);
}

Например, мы можем построить следующие конкретные классы:

public class ConcreteAdaptee : IAdaptee { }

public class ConcreteAdapted : IAdapted { }

public class ConcreteAdapter : IGenericAdapter<ConcreteAdapted, ConcreteAdaptee>
{
    public ConcreteAdapted Adapt(ConcreteAdaptee adaptee)
    {
        // Adapt Logic

        return new ConcreteAdapted();
    }
}

И адаптировать их так:

IGenericAdapter<ConcreteAdapted, ConcreteAdaptee> adapter = new ConcreteAdapter();

var adaptee = new ConcreteAdaptee();
var adapted = adapter.Adapt(adaptee);

var adaptees = new List<ConcreteAdaptee>();
var adapteds = AdaptMultiple(adaptees, adapter);
0 голосов
/ 15 ноября 2018

рассмотрим следующий пример:

interface IDog
{
    void Bark();
}

interface ICat
{
    void Meow();
}
class SomeDog : IDog
{
    public void Bark()
    {
        Console.WriteLine(@"bark bark");
    }
}

class SomeCat : ICat
{
    public void Meow()
    {
        Console.WriteLine(@"meow meow");
    }
}

class CatToDogAdapter : IDog
{
    private ICat cat;
    public CatToDogAdapter(ICat cat)
    {
        this.cat = cat;
    }

    public void Bark()
    {
        cat.Meow();
    }
}

new Dog().Bark(); // bark bark
new CatToDogAdapter().Bark();// meow meow

так работает адаптер.

Допустим, у вас есть модель MyAdaptedData и вы получаете данные, содержащие HotelName, Name, PropertyName, от agoda, booking и tripadviser Для каждой модели бронирования необходимо написать адаптер

AgodaAdapter : MyAdaptedData{
    public AgodaAdapter(AgodaModel agodaModel){
        ....
    }
    public stirng HotelName{
        get{
            return agodaModel.HotelNamebyAgoda;
        }
    }
    ....
}

То же самое для бронирования и TripAdvisor. Шаблон адаптера помогает вам извлекать необходимые данные из внешних моделей.

Затем вам нужно создать конкретный адаптер в зависимости от типа адаптера. Использовать шаблон фабричного метода

MyAdaptedData AdaptersFactory(object adaptee){

    if(adaptee is AgodaModel)
        return new AgodaAdapter(adaptee);
    ....
    if(adaptee is XBookingModel)
        return new XBookingAdapter(adaptee);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...