Обеспечение согласованности именования методов в C # для разных классов - PullRequest
1 голос
/ 27 января 2011

У меня есть серия классов в проекте, которые все делают одно и то же, но на разных объектах.Из-за того, что некоторые из них были закодированы в разное время и разными людьми, существует некоторая непоследовательность в именовании.Я хочу обновить свой код таким образом, чтобы обеспечить некоторую согласованность не только в текущих объектах, но и в новых, которые будут созданы в будущем.Мое понимание программирования заставляет меня верить, что мне нужен либо базовый класс, либо интерфейс, но я не могу понять, как заставить их работать.Я хочу иметь следующие методы:

internal BusinessObject MethodA(EntityObject entity)
internal Void MethodB(EntityContext context, BusinessObject obj, EntityObject entity)

Проблема, с которой я сталкиваюсь, заключается в том, что в каждом классе «BusinessObject» и «EntityObject» будут разными, например, в одном из них могут быть «CarObject and CarEntity» ив другом это будет "BusObject and BusEntity".Я все еще хочу эти два метода, и я все еще хочу, чтобы они назывались MethodA и MethodB. Я просто хочу поменять фактические типы объектов в реализации.Сами реализации будут отличаться, потому что они используют разные объекты.

Я знаю типы объектов во время компиляции, и мне нужно иметь возможность доступа к свойствам объектов, поэтому, если используются универсальные шаблоны, мне нужно привести универсальный тип как правильный тип в реализации.Также реализация MethodA требует создания «нового» BusinessObject, то есть «BusinessObject x = new BusinessObject ()», если это имеет какое-либо значение.

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

Каков наилучший способ справиться с этим?Пример кода будет высоко ценится.

Ответы [ 3 ]

3 голосов
/ 27 января 2011

Дженерики - это путь

Итак, я бы объявил интерфейс (или базовый класс, если вы предпочитаете этот маршрут) по следующим строкам:

internal interface IEntityContext<TEntity>
{
 ???
}

internal interface IMyInterfaceName<TEntity, TBusinessObject>
{
TBusinessObject MethodA(TEntity entity);
Void MethodB(IEntityContext<TEntity> context, TBusinessObject obj, TEntity entity);
}

Тогда, когда дело доходит до реализации вашего класса:

class MyClassThatDoesThisStuff : IMyInterfaceName<Farm, FarmBo>
{
    internal FarmBo MethodA(Farm entity);
    internal Void MethodB(IEntityContext<Farm> context, FarmBo obj, Farm entity);

}

и т.д ...

Вы также можете принудить, чтобы ваши классы произошли от чего-то:

interface IMyInterfaceName<TEntity, TBusinessObject> 
            where TEntity : EntityBase,
                  TBusinessObject : BusinessObjectBase
{
...
}
2 голосов
/ 28 января 2011

Просто чтобы показать решение с абстрактным базовым классом, см. Ответ Neils для получения дополнительной информации ...

public abstract class BaseClass<A,B> {
    internal abstract A MethodA(B entity);
    internal abstract void MethodB(EntityContext context, A obj, B entity);
}

Затем расширьте этот класс:

public class AClass : BaseClass<BusinessObject, EntityObject> {
    internal override BusinessObject MethodA(EntityObject entity) {...}
    internal override void MethodB(EntityContext ctx, BusinessObject obj, EntityObject entity) {...}
}
1 голос
/ 28 января 2011

На самом деле существует три подхода:

  1. Обобщения: где вы указываете контейнерный объект таким образом, что он не зависит от типов BusinessObject и EntityObject.Вы можете немного расширить это, чтобы наложить ограничения на типы объектов, которые дженерик принимает в качестве параметра с общими ограничениями.Большая проблема заключается в том, что на самом деле трудно использовать BusinessObject и EntityObject без приведения и других относительно небезопасных операций.

  2. Наследование: в этом случае вы реализуете BusinessObject в качестве базового класса и требуетчто все объекты, используемые в качестве параметра, будут получены из этого, а также с EntityObject.Затем вы можете поместить любые методы, которые вам действительно нужно использовать, в базовый класс (и при необходимости переопределить их в производных классах.)

  3. Интерфейсы: это на полпути между двумя,Здесь вы говорите, что BusinessObject и EntityObject являются интерфейсами (традиционно их имена начинаются с I, как в IBusinessObject и т. Д.) Здесь вы указываете в интерфейсе методы, которые вам требуется для реализации любого BusinessObject или EntityObject, и, следовательно, можете вызывать их в вашем контейнере.объект.

Поэтому, учитывая ограниченную информацию, которую вы предоставляете, невозможно сказать, какая из них наиболее подходящая.Тем не менее, это три основных варианта.

...