Классы DbSet представляют таблицы базы данных
Имейте в виду, что классы DbSet
, которые вы определяете в DbContext
, представляют таблицы в вашей базе данных.Таблицы представляют собой реальные элементы с реальными столбцами.Каждый столбец представлен свойством в классе, которое вы поместите в свой DbSet
.Если столбцы не являются реальными и представляют отношение, то свойство определяется как виртуальное.Это можно увидеть в виртуальных объявлениях в связанных классах «один ко многим».
В результате «DbSet classes in your
DbContext» - это не интерфейсы, а реальные классы.
С другой стороны, эти классы могут реализовывать ваши интерфейсы.
Производные интерфейсы
У вашего OnlineCustomers
есть только OnlineOrders
.Вы ожидаете, что если вы спросите у OnlineCustomer
их Orders
, что вы получите те же объекты, чем если бы вы попросили у них OnlineOrders
.Так зачем использовать другое имя функции?
Но я хочу другое возвращаемое значение!
Если у вас есть деривация в интерфейсах и функция в вашем производном интерфейсе должна выполнитьтак же, как и базовая функция, за исключением возвращаемого значения, более распространенным является использование одного и того же имени функции и использование явных реализаций интерфейса.
Вы видите это также в IEnumerable.GetEnumerator()
и IEnumerable<T>.GetEnumerator()
Обе функции используют одно и то же имя метода, их возвращаемое значение отличается.Если у вас есть IEnumerable<T>
и вы спрашиваете GetEnumerator()
, вы знаете, что получаете IEnumerator<T>
, который получен из IEnumerator
.
Другой пример: List<T>
реализует IList<T>
, который получен изIList
.Интерфейс IList<T>
реализован нормально, в то время как IList
реализован явно.
Это очень похоже на ваш OnlineUsers
.Что вы хотите, так это то, что если вы спросите у OnlineUser
их Orders
, вы ожидаете только OnlineOrders
.В конце концов, OnlineUsers
имеет только OnlineOrders
.Вы также хотите, чтобы все возвращенные заказы имели интерфейс IOnlineOrders
.Этот интерфейс также реализует IOrders
, поэтому, если вы спросите IOnlineUser
о его Orders
, вы получите его IOnlineOrders
функциональность, а также его IOrder
функциональность.
Это гораздо практичнее, чем позволитьпользователи решают, нужно ли им звонить OnlineOrders
или Orders
. Поэтому я предлагаю:
// unchanged:
interface IOrder {...}
interface IOnlineOrder : IOrder {...}
interface IPhoneOrder : IOrder {...}
interface ICustomer {...}
// similar to IEnumerator<T> and IEnumerator
interface IOnlineCustomer : ICustomer
{
new List<IOnlineOrder> Orders { get; set; }
}
interface IPhoneCustomer : ICustomer
{
new List<IPhoneOrder> Orders { get; set; }
}
Обратите внимание, что я использую ключевое слово new
.Всякий раз, когда я спрашиваю IOnlineCustomer о его Orders
, я не хочу, чтобы «ICustomer.Orders».
Class OnlineCustomer
реализовывал как IOnlineCustomer
, так и ICustomer
.Функции IOnlineCustomer реализованы неявно, функции ICustomer реализованы явно.Эта функция, вероятно, будет вызывать неявные функции Order с помощью Cast.
Попробуйте выполнить следующее:
ICustomer customer = new OnlineCustomer(...);
List<IOrders> orders = customer.Orders();
Ваш отладчик покажет вам, что вызывается OnlineCustomers.Orders, а не явно реализованный ICustomer.Заказы.Хотя вы можете получить доступ только к функциям IOrder
, все возвращаемые элементы фактически являются IOnlineOrders , which of course implement the
IOrder`.
См. Также Зачем реализовывать интерфейс явно?
Finalпримечание
Вы решили сделать возвращаемое значение вашей Orders
функции a List<IOrder>
.Вы уверены, что Orders[4]
имеет определенное значение в вашем контексте?
Не лучше ли вернуть ICollection<IOrder>', or maybe even an
IReadOnlyCollection ? After all the possibility to enumerate and to know the number of elements are key features for your callers. They probably don't want to call
Orders [4] `.
Itдовольно трудно определить правильное значение Order[4]
, или вам придется выполнить какую-то сортировку или что-то в этом роде, что, вероятно, является пустой тратой вычислительной мощности, поскольку большинству абонентов вашей функции на самом деле не нужна отсортированная коллекция.
Рассмотрите возможность изменения возвращаемого значения.