Дженерики и наследование ... Обойти необходимость указания типа <T>? - PullRequest
0 голосов
/ 24 октября 2011

Что ж, мне пришлось переписать это, так как за пять голосов за меня проголосовали за то, что я дал слишком много деталей ... Пойди!

class BaseModel
{
    public T[] Get<T>()
    {
        // return array of T's
    }
    public T Find<T>(object param)
    {
        // return T based on param
    }
    public T New<T>()
    {
        // return a new instance of T
    }
}

class BaseRow
{
    private BaseModel _model;
    public BaseRow(SqlDataReader rdr, BaseModel model)
    {
        // populate properties of inheriting type using rdr column values
    }
    public void Save()
    {
        // calls _model.Save(this);
    }
}

В настоящее время у меня есть несколько классов, которые наследуюткласс BaseModel.Каждый из методов, предоставляемых BaseModel, будет возвращать экземпляр или массив экземпляров типа, который наследует класс BaseRow.

В данный момент при вызове открытых методов в BaseModel через наследующий класс, т.е.

using(DeviceModel model = new DeviceModel())
{
    DeviceRow row = model.Find<DeviceRow>(1);
    DeviceRow[] rows = model.Get<DeviceRow>();
    DeviceRow newRow = model.New<DeviceRow>();
}

Мне нужно указать тип (класс, который наследует класс BaseRow), поскольку методы в BaseModel / BaseRow не знают / не заботятся о том, какой они тип, кроме того, что они наследуют от BaseRow.

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

class DeviceModel : BaseModel
{
    public DeviceRow Find(object param)
    {
        return this.Find<DeviceRow>(param);
    }
}

Примечание. К сожалению, я не могу внедрить или использовать какие-либо сторонние решения.Тем не менее, я пытался использовать Castle Active Record / nHibernate и, честно говоря, они очень большие и тяжелые для того, что должно быть очень простой системой.

Надеюсь, я не предоставил «слишком много» деталей.Если у меня есть, пожалуйста, дайте мне знать.

Спасибо

1 Ответ

2 голосов
/ 25 октября 2011

На вашем месте я бы предложил сделать BaseModel универсальным классом.В ситуации «невозможно победить в любом случае», код, который вы удалили, чтобы осчастливить других, мог бы рассказать мне больше о том, что вы делаете (не критикуя, я ценю вашу позицию).

class BaseModel<T>
{
    public virtual T[] Get()
    {
        // return array of T's
    }
    public virtual T Find(object param)
    {
        // return T based on param
    }
    public virtual T New()
    {
        // return a new instance of T
    }
}

Это ваша база, и у вас есть такие наследники, как:

class DeviceModel : BaseModel<Device>
{
    public override Device New()
    {
        return new Device();
    }
}

Теперь любые общие операции, которые вы определяете в DeviceModel, по умолчанию возвращают или используют строго типизированное устройство.Обратите внимание на виртуальные методы в классе BaseModel.В методах базового класса вы можете предоставить некоторые базовые операции, основанные на использовании T или чего-то еще.В подклассах вы можете определить более конкретное строго типизированное поведение.

Я бы также отметил, что вы можете немного отступить назад и рассмотреть отношения BaseModel и BaseRow.Похоже, что вы определяете параллельную иерархию наследования, которая может иметь тенденцию быть запахом кода (именно здесь вам может пригодиться больше кода - я могу ошибаться в том, как вы используете это).Если ваши перспективы дальнейшего развития таковы, что вам нужно будет добавлять FooRow каждый раз, когда вы добавляете FooModel, это часто является плохим признаком.

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