C# 简单的搜索类
在 ASP.NET 中实现简单可定制的搜索。
引言
本文介绍了一些简单的代码,可以轻松添加搜索功能,用于搜索任何对象(文件、.NET 类)并将搜索结果一起显示在一个视图中。
背景
此演示在 ASP.NET MVC 中呈现,因此基本的 MVC 知识会很有帮助,尽管此解决方案可以应用于其他 .NET 环境。
Using the Code
主要工作是在抽象基类 Searcher
的实现中完成的。在此示例中,在构造函数中创建了一些虚拟数据,然后在 Search
方法中查询匹配项,并将其投影到 SearchResult
中。请注意 RouteInformation
的填充方式。RouteInformation
字典中的条目将用于在 MVC 视图中创建 ActionLink
。
public class ProductSearcher : Searcher
{
private List<Product> Products { get; set; }
public ProductSearcher()
{
//Dummy up some data here...
Products = new List<Product>();
}
public override IEnumerable<SearchResult> Search(string searchTerm)
{
var result = Products.Where(p => p.Description.ToLower().Contains(
searchTerm.ToLower()) ||
p.Name.ToLower().Contains(searchTerm.ToLower()))
.Select(p => new SearchResult
{
Category = "Product",
Description = p.Name,
Id = p.ProductId,
OriginatingObject = p
}).ToList();
result.ForEach(p => p.RouteInformation = GetRouteInfo(p.Id));
return result;
}
private static Dictionary<string, string> GetRouteInfo(int id)
{
return new Dictionary<string, string>
{
{"controller", "product"},
{"action", "details"},
{"Id", id.ToString()}
};
}
}
SearchCore
使用 Searcher
实现的 List
初始化,它应该使用这些实现来构建搜索结果。当调用 Search
时,它只是遍历它们,调用它们的 Search
方法并汇总结果。
public class SearchCore
{
private List<Searcher> Searchers { get; set; }
public SearchCore(List<Searcher> searchers)
{
Searchers = searchers;
}
public IEnumerable<SearchResult> Search(string searchTerm)
{
var result = new List<SearchResult>();
foreach (Searcher searcher in Searchers)
{
result.AddRange(searcher.Search(searchTerm));
}
return result;
}
}
搜索控制器
搜索控制器只有一个 ActionResult
,它创建我们的 Searcher
实例并将它们添加到列表中,然后将该列表传递给 SearchCore
。它使用秒表来测量执行搜索所花费的时间。可以启用 Search
方法上的缓存以提高性能。
private SearchCore SearchCore { get; set; }
public SearchController()
{
var searchers = new List<Searcher> {new ProductSearcher(), new CompanySearcher()};
SearchCore = new SearchCore(searchers);
}
//Uncomment below to enable caching.
//[OutputCache(VaryByParam = "searchTerm", Duration = 180)]
[HttpPost]
public ActionResult Search(string searchTerm)
{
var model = new SearchResponse();
//Use a stopwatch to measure the time it takes to perform the search.
var s = new System.Diagnostics.Stopwatch();
s.Start();
model.Results = SearchCore.Search(searchTerm);
s.Stop();
model.OriginalSearchTerm = searchTerm;
model.TimeTaken = s.Elapsed;
return View(model);
}
搜索视图
搜索视图只是打印原始搜索词和所花费的时间,并遍历结果,打印链接(使用 RouteInfoLink
扩展方法),然后调用原始对象的 DisplayTemplate
(无论是什么)。Display Templates 存储在 Search 文件夹的 DisplayTemplates 子文件夹中。
@model SimpleSearch.SearchResponse
<html>
<head>
<title>Search Results</title>
</head>
<body>
<h2>Search Results</h2>
@Html.Raw(string.Format("Your search for <strong>{0}</strong> returned {1}
results in {2} seconds", Model.OriginalSearchTerm, Model.Results.Count(),
Math.Round(Model.TimeTaken.TotalSeconds, 3)))<br />
@*Only meaningful if caching is enabled on the controller*@
<em>@String.Format("Cached at {0}", DateTime.Now.ToShortTimeString())</em>
@foreach (var item in Model.Results)
{
<section style="border: 0px none; display: block; float: none; padding: 0px">
<h3>@item.Category - @Html.RouteInfoLink(item.Description, item.RouteInformation)</h3>
@Html.DisplayFor(m =>
显示模板
DisplayTemplate
只是以其强类型类型命名的标准 Razor 片段。
@model Search.Models.Product
<section style="border: 0px none; display:block; float:none; padding: 0px">
@Model.Name<br />
<b>Short Name: </b>@Model.ShortName<br/>
@Model.Description<br/>
<h3>£@Model.Price</h3>
</section>
关注点
这只是一个非常基本的实现,但它展示了如何使用相对较少的代码来完成真正有用的事情。