Интерфейс и абстрактное наследование c # - PullRequest
0 голосов
/ 11 сентября 2018

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

public interface IBaseInterface {
    public IBaseInterface ChainableMethod()
}

public abstract AbstractClassThatHelps<T> where T: IBaseInterface n {
    public T ChainableMethod() {
        return (T) this;
    }
}

public interface IDerived : IBaseInterface { }

public class DerivedClass : AbstractClassThatHelps<IDerived>, IDerived { }

IDerived derived =  new DerivedClass();
derived.ChainableMethod().ChainableMethod();

Проблема, с которой я здесь сталкиваюсь: почему нельзя вернуть T, когда показано, что он реализует контракт IModel?

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


Фактическая реализация: У нас есть несколько моделей (DerivedClass), которые реализуют соответствующие им IDerived для внедрения зависимостей. Им нужны помощники, потому что я не хочу повторяться. Итак, мы используем AbstractClassThatHelps в качестве базы, но, поскольку мы имеем дело с цепочечными методами, нам нужен этот базовый класс, чтобы знать, что возвращать, поэтому и дженерики. IBaseInterface можно рассматривать как IModel. Например, ChainableMethod можно увидеть как GetAll().

Ответы [ 3 ]

0 голосов
/ 11 сентября 2018

Для того, чтобы следующий код работал, AbstractClassThatHelps<T> должен реализовать IBaseInterface.Как вы можете вернуть this, если this не IBaseInterface

public abstract AbstractClassThatHelps<T> where T: IBaseInterface n{
    public T ChainableMethod(){
        return this;
    }
}

Редактировать: я не пользователь, что решает этот дизайн, но вот моя попытка того, чего вы пытаетесь достичь →

public interface IBaseInterface
{
    IBaseInterface ChainableMethod();
}

public abstract class AbstractClassThatHelps<T>:IBaseInterface where T : IBaseInterface{
    public T ChainableMethod()
    {
        IBaseInterface i = this;
        return (T)i.ChainableMethod();
    }

    IBaseInterface IBaseInterface.ChainableMethod()
    {
       return this;
    }
 }

public class Concrete : AbstractClassThatHelps<Concrete>
{
}
0 голосов
/ 11 сентября 2018

Это работает, ваш код был полон синтаксических ошибок:

public interface IBaseInterface
{
    IBaseInterface ChainableMethod();
}

public abstract class AbstractClassThatHelps : IBaseInterface
{
    public IBaseInterface ChainableMethod()
    {
        return this;
    }
}

public interface IDerived : IBaseInterface
{

}

public class DerivedClass : AbstractClassThatHelps, IDerived
{

}


internal static class Program
{
    public static void Main()
    {

        IDerived derived = new DerivedClass();
        derived.ChainableMethod().ChainableMethod();
    }
}

Вы также можете попробовать это:

public interface IBaseInterface
{
    IBaseInterface ChainableMethod();
}

public abstract class AbstractClassThatHelps<T> : IBaseInterface where T : class, IBaseInterface
{
    public T ChainableMethod()
    {
        return this as T;
    }

    IBaseInterface IBaseInterface.ChainableMethod()
    {
        return ChainableMethod();
    }

}

public interface IDerived : IBaseInterface
{
    IDerived Hello();
}

public class DerivedClass : AbstractClassThatHelps<IDerived>, IDerived
{
    public IDerived Hello()
    {
        Console.WriteLine("Hello");
        return this;
    }
}


internal static class Program
{
    public static void Main()
    {

        AbstractClassThatHelps<IDerived> derived = new DerivedClass();
        derived.ChainableMethod().Hello().ChainableMethod();
    }
}
0 голосов
/ 11 сентября 2018

Вы можете вернуть экземпляр из T, но возвращаемый тип не может быть T, но должен быть IBaseInterface, потому что этого требует интерфейс.

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