2017-02-22 39 views
1

Я создал интерфейс, который имеет два производных класса, как показано ниже в фрагментах кода. Я хочу получить доступ к элементам этих производных классов в запросе Linq, но я не могу этого сделать.Доступ к свойствам производных классов из интерфейса в запросе Linq?

Структура модели Класс:

public interface IDirDetails 
{ 
} 
public class DirectoryDetails: IDirDetails 
{ 
    public string[] PathElements { get; set; } 
    public string[] ApplicationList { get; set; } 

    public List<DirectoryItemInfo> Items { get; set; } 
} 
public class DirectoryItemInfo: IDirDetails 
{ 
    public string FileName { get; set; } 
    public string FileType { get; set; } 
    public string FileSize { get; set; } 
    public string FileIcon { get; set; } 
    public DateTime FileModified { get; set; } 
    public string FilePath { get; set; } 
} 

форма кода, где я пытаюсь получить доступ к этим членам:

List<IDirDetails> data = LoadData();     
int totalRecords = data.Count; 

if (!string.IsNullOrEmpty(search) && !string.IsNullOrWhiteSpace(search)) 
{ 
    // Apply search 
    data = data.Where(p => p.FileName.ToString().ToLower().Contains(search.ToLower()) || //not allowing to access FileName 
          p.FileSize.ToLower().Contains(search.ToLower()) ||    //not allowing to access FileSize 
          p.FileModified.ToString().ToLower().Contains(search.ToLower())).ToList(); //not allowing to accessFileModified 
} 

ниже то, как я устанавливаю значения для этих классов в LoadData()

public List<IDirDetails> LoadData() 
{ 
    string userName = HttpContext.User.Identity.Name; 
    var user = _context.Users.FirstOrDefault(m => m.UserName == userName);   
    string[] appList = null; 
    var allDirDetails = new List<IDirDetails>(); //obj of an Interface 
    var allAppExist = _context.UserApplications.Any(ua => ua.AppId == 17 && ua.UserId == user.Id); 

    appList = (from a in _context.Applications 
       join ua in _context.UserApplications on a.Id equals ua.AppId 
       where ua.UserId == user.Id 
       select a.AppName).ToArray(); 

    DirectoryDetails dirDetails = new DirectoryDetails(); 
    dirDetails.ApplicationList = appList; 

    List<DirectoryItemInfo> dirItems = new List<DirectoryItemInfo>(); 
    dirDetails.Items = dirItems; 

    allDirDetails.Add(dirDetails); // adding values into DirectoryDetails 

    string requestPath = Request.Path.Value; 

    string[] requestPathParts = requestPath.Split(new string[] { "/" }, StringSplitOptions.RemoveEmptyEntries); 
    dirDetails.PathElements = requestPathParts; 

    var aapId = _context.Applications.FirstOrDefault(a => a.AppName == requestPathParts[0].ToString()); 

    string[] physicalPaths = (from ap in _context.ApplicationPathElements 
           join a in _context.Applications on ap.AppId equals a.Id 
           where a.Id == aapId.Id 
           select ap.AppPathElement).ToArray(); 
    if (physicalPaths != null && physicalPaths.Length > 0) 
    { 
     foreach (string indexPath in physicalPaths) 
     { 
      DirectoryItemInfo details = GetDirectoryInfo(indexPath, indexPath + "/", DateTime.MinValue);   
      allDirDetails.Add(details); // adding values into DirectoryItemInfo 
     } 
    }    
    return allDirDetails; 
} 

Может кто-нибудь, пожалуйста, предложите, как мне получить доступ к требуемым членам deri ved классы из интерфейса?

ответ

1

Простой ответ на ваш вопрос: просто брось

data = data.Cast<DirectoryItemInfo>().Where(p => p.FileName.ToString().ToLower().Contains(search.ToLower()) || 
         p.FileSize.ToLower().Contains(search.ToLower()) ||    
         p.FileModified.ToString().ToLower().Contains(search.ToLower())).ToList(); 

или использовать OfType

data = data.OfType<DirectoryItemInfo>().Where(p => p.FileName.ToString().ToLower().Contains(search.ToLower()) || 
         p.FileSize.ToLower().Contains(search.ToLower()) ||    
         p.FileModified.ToString().ToLower().Contains(search.ToLower())).ToList(); 

Правильный ответ: Что-то не так с вашей моделью. Либо вам не нужен список интерфейса, но список определенного типа, или вы должны перенести эти свойства в интерфейс.

Например, ваш метод LoadData возвращает список интерфейсов, но в вашем примере вы используете его как список определенного класса. Вы можете изменить его, как:

public List<T> LoadData<T>() where T:IDirDetails 
{ 
    // return specific List 
} 

После того, что вы могли бы назвать его как:

List<DirectoryItemInfo> data = LoadData<DirectoryItemInfo>(); 

и вам не нужны актеры. Где-то в LoadData вы должны решить, какие элементы вы вернете.

+0

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

+0

@RahulNagrale Я не знаю, я вижу весь ваш код, я сделал одно предложение в ответе, но это действительно зависит от того, что вы делаете в точности. –

+0

появляется ошибка, когда я возвращаю 'List ' из 'LoadData()', Ошибка: 'CS0029 \t Невозможно неявно преобразовать тип 'System.Collections.Generic.List ' to 'System .Collections.Generic.List '' –

0

Вы можете взять все элементы из списка 'data' с помощью типа 'DirectoryItemInfo', используя метод 'OfType', и вернуть результат из списка 'Where' to 'IDirDetails'.

data = data.OfType<DirectoryItemInfo>() 
      .Where(p => 
        p.FileName.ToString().ToLower().Contains(search.ToLower()) || 
        p.FileSize.ToLower().Contains(search.ToLower()) || 
        p.FileModified.ToString().ToLower().Contains(search.ToLower())) 
      .ToList<IDirDetails>(); 
0

Доступ к тем членам, которые определены в вашем интерфейсе, доступны только для них. Если вам нужно получить доступ к элементам конкретной реализации этого интерфейса, вам понадобится экземпляр конкретной реализации (в вашем случае экземпляр DirectoryDetail или DirectoryItemInfo.

Вы можете сделать некоторые вещи с отливкой как другие Участники говорили, но вы по-прежнему доступа экземпляр конкретной реализации в той или другой.

0

Использование OfType для фильтрации типа

List<IDirDetails> data = LoadData();     
int totalRecords = data.Count; 

if (!string.IsNullOrEmpty(search) && !string.IsNullOrWhiteSpace(search)) 
{ 
    // Apply search 
    data = data.OfType<DirectoryItemInfo>().Where(p => p.FileName.ToString().ToLower().Contains(search.ToLower()) || 
          p.FileSize.ToLower().Contains(search.ToLower()) ||    
          p.FileModified.ToString().ToLower().Contains(search.ToLower())).Cast<IDirDetails>().ToList(); 
} 
+0

'Cast' не будет работать, если в списке есть' DirectoryDetails'. – xwlantian