从 Linq 查询中的接口访问派生 类 的属性?
Access Properties of Derived Classes from an Interface in Linq Query?
我创建了一个具有两个派生 类 的接口,如下面的代码片段所示,我想在 Linq
查询中访问那些派生 类 的成员,但是我做不到。
型号Class结构:
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;
}
有人可以建议我应该如何从接口访问派生 类 的必需成员吗?
对你的问题的简单回答是:直接施法
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
方法 return 是一个接口列表,但在您的示例中,您将它用作特定 class 的列表。您可以将其更改为:
public List<T> LoadData<T>() where T:IDirDetails
{
// return specific List
}
之后你可以这样称呼它:
List<DirectoryItemInfo> data = LoadData<DirectoryItemInfo>();
而且你不需要强制转换。在 LoadData
的某处,您应该决定要 return.
哪些元素
您可以使用 '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>();
您只能访问由您的接口定义的那些成员。如果您需要访问该接口的具体实现的成员,则需要具体实现的实例(在您的情况下,是 DirectoryDetail
或 DirectoryItemInfo
.
的实例
您可以像其他成员所说的那样通过转换来做一些事情,但是您仍然以某种方式访问具体实现的实例。
使用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();
}
我创建了一个具有两个派生 类 的接口,如下面的代码片段所示,我想在 Linq
查询中访问那些派生 类 的成员,但是我做不到。
型号Class结构:
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;
}
有人可以建议我应该如何从接口访问派生 类 的必需成员吗?
对你的问题的简单回答是:直接施法
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
方法 return 是一个接口列表,但在您的示例中,您将它用作特定 class 的列表。您可以将其更改为:
public List<T> LoadData<T>() where T:IDirDetails
{
// return specific List
}
之后你可以这样称呼它:
List<DirectoryItemInfo> data = LoadData<DirectoryItemInfo>();
而且你不需要强制转换。在 LoadData
的某处,您应该决定要 return.
您可以使用 '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>();
您只能访问由您的接口定义的那些成员。如果您需要访问该接口的具体实现的成员,则需要具体实现的实例(在您的情况下,是 DirectoryDetail
或 DirectoryItemInfo
.
您可以像其他成员所说的那样通过转换来做一些事情,但是您仍然以某种方式访问具体实现的实例。
使用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();
}