C# получают доступ к свойствам родового объекта

У меня есть метод, который считает количество Контактов, которые каждый Поставщик, Клиент и Производитель имеют (это - сценарий для попытки, делают объяснение легче!)

Модели все создаются Linq к классам SQL. У каждого Поставщика, Клиента и Производителя может быть один или несколько Контактов

public int CountContacts<TModel>(TModel entity) where TModel : class
{
    return entity.Contacts.Count();
}

Вышеупомянутое, конечно, не работает, потому что 'объект' универсален и не знает, имеет ли это свойство 'Contacts'. Кто-то может помочь с тем, как достигнуть этого?

9
задан Jimbo 21 May 2010 в 14:08
поделиться

5 ответов

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

public int CountContacts<TModel>(TModel entity) where TModel : IContacts


interface IContacts
{
   IList<Contact> Contacts {get;} //list,Ilist,ienumerable
}
6
ответ дан 4 December 2019 в 21:08
поделиться

Есть несколько вариантов решения проблемы.

  • Наследовать один и тот же абстрактный класс или реализовать один и тот же интерфейс с объектами. (Остальные исчерпали этим все возможные решения.)
  • Если вы используете .NET 4, ключевое слово dynamic может быть самым дешевым решением.

Например:

public int CountContacts(dynamic entity)
{
    return entity.Contacts.Count();
}

Это означает, что объект не будет оцениваться до времени выполнения, и если вы случайно вызовете метод для объекта, у которого нет контактов свойство, это вызовет исключение.

0
ответ дан 4 December 2019 в 21:08
поделиться

Все ответы на данный момент верны, но также следует указать, что причина того, что ваш код не компилируется, заключается в том, что типы TModel не имеют ничего общего. Указав общий базовый класс или интерфейс, который они все реализуют с вашим свойством «Контакты», ваш код будет работать.

1
ответ дан 4 December 2019 в 21:08
поделиться

Один из способов навязать контракт , в котором Поставщики, Заказчики и Производители должны содержать свойство Контакты , - это интерфейсы. Сделайте так, чтобы каждая сущность реализовывала один интерфейс, который содержит свойство Контакты :

interface IContactable
{
   IEnumerable<Contact> Contacts {get;}
}


public int CountContacts<TModel>(TModel entity) where TModel : class, IContactable
{
    return entity.Contacts.Count();
}
3
ответ дан 4 December 2019 в 21:08
поделиться

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

Из MSDN

public interface ICountable<out T>  
{
    int Count{ get; }
}
public class MyCollection : ICountable<string>, ICountable<FileStream>
{  
    int ICountable<string>.Count
    {
        get { return 1; }
    }
    int ICountable<FileStream>.Count
    {
        get { return 2; }
    }
}
0
ответ дан 4 December 2019 в 21:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: