从Linq查询中的接口访问派生类的属性?

时间:2017-02-22 07:11:09

标签: c# linq asp.net-core-webapi

我创建了一个具有两个派生类的接口,如下面的代码片段所示,我想在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;
}

有人可以建议我应该如何从界面访问派生类的必需成员?

4 个答案:

答案 0 :(得分: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的某个地方你应该决定你将返回哪些元素。

答案 1 :(得分:0)

您可以使用'OfType'方法从'data'列表中获取所有带有'DirectoryItemInfo'类型的项目,并将'Where'的结果转换回'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>();

答案 2 :(得分:0)

您只能访问由您的界面定义的成员。如果您需要访问该接口的具体实现的成员,您将需要具体实现的实例(在您的情况下,是DirectoryDetailDirectoryItemInfo的实例。

你可以像其他成员所说的那样使用强制转换做一些事情,但是你仍然以某种方式访问​​具体实现的实例。

答案 3 :(得分: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(); 
}