2010-05-21 3 views
9

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

Модель все созданным Linq to SQL. Каждый поставщик, клиент и производитель может иметь один или несколько контактов

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

выше, конечно, не работает, потому что «сущность» является общим и не знает, имеет ли это свойство «Контакты». Может ли кто-нибудь помочь в том, как это сделать?

ответ

6

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

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


interface IContacts 
{ 
    IList<Contact> Contacts {get;} //list,Ilist,ienumerable 
} 
+0

+1 За исключением вас не следует возвращать Список - желательно IList <> или, возможно, даже IEnumerable <> – n8wrl

+0

Хорошая точка. Я быстро печатал и не думал об этом. – kemiller2002

+0

Проблема в том, что классы LINQ to SQL используют EntitySets для такой цели, а свойство Contacts с типом EntitySet не будет реализовывать свойство интерфейса, поэтому ему придется реализовать его вручную в каждом классе. – Venemo

3

Один из способов наложить контракт, где поставщики, клиенты и Manufactors должны содержать Contacts свойство с интерфейсами. Сделайте каждый объект реализовать один интерфейс, который содержит Contacts свойство:

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


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

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

От 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; } 
    } 
} 
1

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

0

Существует несколько решений проблемы.

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

Например:

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

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