将约束应用于类,遵守界面

时间:2018-11-15 02:22:45

标签: c# generics interface adapter

我要求能够执行许多外部模型到我自己的内部模型的转换。

我决定应用Adapter模式,但我想使其尽可能通用。如此有效,我希望它能够处理两个“单个” POCO,但是如果我需要通过/调整集合,那么它也必须工作,例如:

IEnumerable<IAdaptee> OR IList<TAdaptee>

并返回我自己的适应对象:

IEnumerable<IAdapted> OR IList<TAdapted>

我想做以下事情:

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

当我构建“ Adapter”类并实现上面的接口时,我遇到的困难是,出现约束不匹配错误。这当然是有道理的,因为如果我将约束应用于实现接口的类,而接口没有约束,则当然会发生错误。

所以:

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 :(得分:1)

如果您可以访问外部模型,则可以使用界面作为标记:

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);

答案 1 :(得分:0)

考虑以下示例:

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模型,并且从agoda,booking和tripadviser检索包含HotelName,Name,PropertyName的数据 对于每种预订模式,您需要编写适配器

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

与预订和旅行顾问相同。 适配器模式可帮助您从外部模型检索必要的数据。

然后,您需要根据适配器类型创建特定的适配器。使用Factory方法模式

MyAdaptedData AdaptersFactory(object adaptee){

    if(adaptee is AgodaModel)
        return new AgodaAdapter(adaptee);
    ....
    if(adaptee is XBookingModel)
        return new XBookingAdapter(adaptee);
}