[DB4O]DB4O发布7.8版本数据库引擎

mikel阅读(877)

下载地址:
http://www.db4o.com/community/download.aspx?file=db4o-7.8-net35.zip
介绍:

db4o 7.8 Release is available for immediate download! For more details please check the release notes.

Highlighted Contributions
from the community projects blog

  • Solving class loading issues with db4o and OSGi: Lukas Neukom kindly contributed a proof of concept (source code included) where he shows two ways to solve class loading issues with db4o and OSGi (by either using fragments or by implementing a bundle extender).
  • New podcast about object databases and db4o: Alt.NET Podcast just featured db4o in Episode 14 entitled "Object Databases". Guests to the podcast are Rob Conery and James Avery.
  • Tips on indexing and query optimization: This blog post shows some indexing basics and performance tips by Arne Claassen. Among other things Arne shows you which assemblies to include to make sure your native queries can be optimized.
  • db4o v7.4 for Mono: Arne Claassen has been playing with db4o under Mono and came up with a DLL for db4o v7.4 that works beautifully across .NET and Mono from a single build (dll available for download).
  • Using db4o for unit test results verification: The author of "Nails and Hammers" blog shows how to use the TestSpy pattern (described in Gerard Meszaros' xUnit Test Patterns) in combination with db4o. TestSpy is a class that can be ?injected' in a tested class in order to instrument and capture its behaviour. In this blog post TestSpy is used to persist objects created in the tested method to be verified at a later stage.
  • New db4o sample app: BookStore.NET: a digital book management application by Mihnea Radulescu using db4o v7.4 and C# 2.0, targeting the .NET Framework 2.0. It allows the user to manage all of its digital books and articles (pdf, chm, html, doc, rtf, etc.) on the computer in an elegant and effective way (files are stored as binary in the database file).
  • Follow db4o on Twitter!: db4objects is now broadcasting news and updates on Twitter!

[技术]09/10年关注的8项移动性技术

mikel阅读(779)

市场分析公司Gartner近期发布了一份报告,预测了在未来2年内将影响移动行业的8项移动性技术。该公司副总裁及分析师Nick Jones表示,该公司在报告中列出的技术将很快的演进,同时有些问题也需要尽快解决。

蓝牙3.0

蓝牙3.0 这项技术是毫无异议的当然之选。蓝牙3.0的技术标准将在今年发布,并且预计支持蓝牙3.0标准的各类设备将会在2010年商用。目前,对3.0标准最大 的期望在于更快的速度,据说在近距离的传送速度可以达到480Mbps,而10米左右距离的传送速度可到100Mbps。同时蓝牙3.0还将支持一种超低 功耗模式,Gartner预测这将使得更多更新的外围设备、感应器和其他类似健康监控类的应用成为可能。蓝牙3.0还将实现向后兼容,允许旧版本的设备与 新版本设备通信,所以很明显未来几年蓝牙3.0技术将得到大量应用。

移动设备用户界面/移动设备上的web应用和widget应用

在报告中,移动设 备用户界面和移动设备上的web/widget应用是分开列出的两项,但我们认为可以把她们归在一起。这两者都是关于移动计算设备快速成为一个面向消费者 用户新平台,消费者在这个平台上可以实现关于B2E(企业对员工)和B2C(企业对用户)的任何应用。(gartner没有包含B2B企业对企业在内)如 今像iPhone, Android, Blackberry, 以及马上发布的Pre这类智能手机,都可以提供更好的浏览互联网的用户界面,使得更多的人可以使用互联网应用。类似Widget的程序,包括那些大量的瘦 客户端技术,将变得越来越普遍,特别是在B2C这一领域。不过移动互联网行业还面临很多挑战。比如,在报告中提到目前还没有为像数码相机和GPS等手持设 备设计的浏览器标准。

定位信息服务

通过GPS定位技术或者WiFi三角定位技术等实现的定位信息服务,为移动社 交网络和在线服务开启了新的可能性。那些快速接受并应用新技术的用户已经很熟悉像Brightkite和Loopt这种可以通过网络向你的朋友提供你的位 置信息的社交网络服务。但是我们都还处在尝鲜阶段。例如,iPhone上的即时通信软件Palringo,刚刚增加了位置信息服务。这一功能使得用户可以 看到他们的联系人现在离他们有多远,这给移动通信带来了全新的体验。未来的一两年,我们期待这类技术变的更加普遍,当然它也带来了隐私类的问题。你希望你 的在线朋友群知道你准确的位置信息么?是不是你关闭了定位信息就表示你在做啥#¥%的事儿那?(你的老婆、丈夫或者老板会开始怀疑了)作为社会的一份子,我们得尽快考虑好这些问题。

近距离通信(NFC

NFC技术为消费者提供一种手段来使用他们的移动电 话实现类似付账这种功能。其实这一应用已经在世界上很多国家开始普及了,但不是所有国家,特别是美国。不幸的是,Gartner预测这一移动支付系统在像 美国和西欧这样的成熟市场不会很快得到普及。相反的,NFC技术更可能在新兴市场快速普及。这一技术还可以应用到其他领域,比如在手机和电子相框间传照 片,同样的,在成熟市场也存在较大的不确定性。

802.11n与无线(蜂窝)宽带

802.11n是无线局域网的一个标准,initially gave us pause(不确定意思)。尽管还没有正式标准化,这一技术已经开始普及了。然而,在他成为主流之前,还不大能渗透到移动领域的各个地方。就算是最激进的iphone目前也只支持802.11b/g。

另一方面,另一项网络连接技术,蜂窝无线宽带则更在不断提高速度,反而会使WIFI变得不再是必须的技术了。除了手机外,笔记本电脑制造商们也将继续将这一技术通过更高性能的芯片集成到他们的笔记本或上网本产品中,而不再只是通过额外的上网卡这类设备。

显示技术

显示技术也将在未来看到进步。类似有源像素显示、无缘显示和超微投影仪这类新技术将带来一定的影响。今年在CES展会上看到的超微投影仪是种小尺寸的便携投影仪,肯定将创造新的移动应用。在非正式场合没有投影仪的情况下,即时演示将越来越普遍。Gartner预测2009和10年将要出现的不同类型的显示技术将成为设备制造商之间的分水岭,并且将影响用户的选择。

[Lucene]Lucene.net实现自定义排序笔记

mikel阅读(674)

在Lucene.net实现自定义排序,需要实现两个Lucene.Net.Search的两个接口:
public interface SortComparatorSource
{
   ScoreDocComparator NewComparator(IndexReader reader , System.String fieldname) ;
}

public interface ScoreDocComparator
{
   int Compare(ScoreDoc i , ScoreDoc j) ;
   System.IComparable SortValue(ScoreDoc i) ;
   int SortType() ;
}

涉及到的一个类:
public class ScoreDoc
{
   public float score ;
   public int doc ;
   public ScoreDoc(int doc , float score)
   {
      this.doc = doc ;
      this.score = score ;
   }
}

Lucene.net 2.0包含的SortType有:
在Lucene.Net.Search.SortField里定义的:
public class SortField
{
   public const int SCORE = 0 ;  //相关度
   public const int DOC = 1 ;    //文挡号
   public const int AUTO = 2 ;   //自动识别
   public const int STRING = 3 ; //字符型
   public const int INT = 4 ;    //int
   public const int FLOAT = 5 ;  //float
   public const int CUSTOM = 9 ; //自定义
   …..
}

少了DateTime,那就实现DateTime类型的自定义排序来测试下:
Lucene.Net.Search.ScoreDocComparator接口的实现类:
    public class DateDocComparator : Lucene.Net.Search.ScoreDocComparator
    {
        private string fieldname = null;
        private System.IComparable[] cachedValues ;

        public DateDocComparator(System.IComparable[] cachedValues, string fieldname)
        {
            this.cachedValues = cachedValues;
            this.fieldname = string.Intern(fieldname) ;
        }

        public int Compare(ScoreDoc i, ScoreDoc j)
        {
            return this.cachedValues[i.doc].CompareTo(this.cachedValues[j.doc]) ;
        }

        public System.IComparable SortValue(ScoreDoc i)
        {
            return this.cachedValues[i.doc] ;
        }

        public int SortType()
        {
            return Lucene.Net.Search.SortField.CUSTOM ;
        }
    }

Lucene.Net.Search.SortComparatorSource接口的实现类:
    public class DateSortComparatorSource : Lucene.Net.Search.SortComparatorSource
    {
        public ScoreDocComparator NewComparator(Lucene.Net.Index.IndexReader reader, System.String field)
        {
            return new DateDocComparator(GetCustom(reader, field), field);
        }

        protected virtual System.IComparable[] GetCustom(Lucene.Net.Index.IndexReader reader, System.String field)
        {
                System.IComparable[] retArray = new System.IComparable[reader.MaxDoc()];
                Lucene.Net.Index.TermDocs termDocs = reader.TermDocs();
                Lucene.Net.Index.TermEnum termEnum = reader.Terms(new Lucene.Net.Index.Term(field, ""));
                try
                {
                    do
                    {
                        Lucene.Net.Index.Term term = termEnum.Term();
                        if (term == null || term.Field() != field)
                            break;
                        System.IComparable termval = Lucene.Net.Documents.DateTools.StringToDate(term.Text()) ;
                        termDocs.Seek(termEnum);
                        while (termDocs.Next())
                        {
                            retArray[termDocs.Doc()] = termval;
                        }
                    }
                    while (termEnum.Next());
                }
                finally
                {
                    termDocs.Close();
                    termEnum.Close();
                }
                return retArray;
        }
    }

使用:
Sort sort = new Sort(new SortField("datecreated",new DateSortComparatorSource(),true)) ;

[Lucene]Lucene.net搜索结果排序(单条件和多条件)

mikel阅读(675)

Lucene支持对搜索条件的排序,一个条件或者多个条件,以及是升序还是降序,部分代码如下:

        string INDEX_STORE_PATH = Server.MapPath("index");  //INDEX_STORE_PATH 为索引存储目录
        string keyword = TextBox2.Text;                     //搜索内容

        Hits myhit 
= null;
         
        IndexSearcher mysea 
= new IndexSearcher(INDEX_STORE_PATH);
        QueryParser q 
= new QueryParser("indexcontent"new StandardAnalyzer());
        Query query 
= q.Parse(keyword);
        Sort sort 
= new Sort();
        SortField f 
= new SortField("createdate", SortField.STRING, true);//按照createdate字段排序,true表示降序
        sort.SetSort(f);
        
//多个条件排序
        
//Sort sort = new Sort();
        
//SortField f1 = new SortField("createdate", SortField.DOC, true);
        
//SortField f2 = new SortField("bookname", SortFiedl.INT, false);
        
//sort.setSort(new SortField[] { f1, f2 });
        myhit = mysea.Search(query, sort);
        Response.Write(
"关于:" + keyword + "  搜索到" + myhit.Length() + "个结果<br>");

对于数据量大(索引文件大于50M)的索引,尽量不要用索引中的字段排序,要用索引ID排序(INDEXORDER);两者效率相差近10倍。
注:lucene.net版本为:2.0.0.4

[MVC]使用Asp.net MVC, Jquery, Jquery UI构建基于Ajax的RIA应

mikel阅读(835)

前天初学ASP.NET MVC,发现有些东西用Web Form来做的确会比较方便. 但ASP.NET MVC也有它的优点. 它如果跟JQueryJQuery UI结合起来做基于Ajax的应用实在是太方便了!!下面用图形说明:

这次还是做一个树形控件.需要特别说明的是,这个Demo全部都是用Ajax做的,增删改都无刷新,而且可以方便地换肤..以下是最终的效果图:

image

新建分类. 用上Effect就跟Flex有得拼了..而且做出这种效果非常方便.

image

编辑分类.. 一样的开dialog

 image

 

 image

删除功能.

image

image

 

以下是另一种主题.. 换主题非常方便 .. 换个css就OK

 

image

这个是黑色的主题.. 官方也有很多下载..

 

image

感觉真是太强了..

 

下面简要说一下它的ajax功能怎么方便法..以下功能用到了NbearLite. 我一直很喜欢用NbearLite..

我们要做一个添加数据的功能.于是写了以下Controller

 [AcceptVerbs(HttpVerbs.Post)]
public ContentResult Create(FormCollection f)
{
int pid = 0; if (!int.TryParse(f["ParentID"], out pid)) pid = 0;
Gateways.DB.Insert(Tables.Tree)
.AddColumn(Tables.Tree.pid, pid)
.AddColumn(Tables.Tree.title, f["CategoryName"])
.AddColumn(Tables.Tree.description, f["Description"])
.Execute();
return Content("新建成功!");
}

我们一般都会写下以下的view

<button id="btn-createCategories" class="ui-button ui-state-default ui-corner-all">
新建分类</button><br />

<div id="createCategories" style="display: none;" title="新建分类">
<p>
新建分类</p>
<% using (Html.BeginForm("Create", "Categories", FormMethod.Post, new { id = "frm-CreateCategories", name = "frm-CreateCategories" }))
{
List<OtisTreeNode> treeList = this.Model as List<OtisTreeNode>;
%>
<fieldset>
<label for="CategoryName">
CategoryName</label>
<% =Html.TextBox("CategoryName")%>
<label for="Description">
Description</label>
<% =Html.TextBox("Description")%>
<label for="ParentID">
父类</label>
<% =Html.TreeSelect(treeList , "ParentID", "请选择父类", "&nbsp;&nbsp;", "", "")%>
</fieldset>
<% } %>
</div>

可以看出,如果加上一个submit 按钮,以上,已经可以工作了.或许Controller应该要返回一个ActionResult,并做一些try{} catch{}..但基本结构是这样..

下面我们再为它加上ajax功能和用上jQuery的UI..

引入相关JavaScript和css如下:

 <link href="/Scripts/Jquery/themes/darkness/ui.all.css" rel="stylesheet" type="text/css" />
<style type="text/css">
label, input
{
display: block;
}
body
{
font-size: 12px;
}
input.text
{
margin-bottom: 12px;
width: 95%;
padding: .4em;
}
fieldset
{
padding: 0;
border: 0;
margin-top: 25px;
}
.ui-button
{
margin: 2px 4px;
padding: 2px;
text-decoration: none;
cursor: pointer;
position: relative;
text-align: center;
}
.ui-dialog .ui-state-highlight, .ui-dialog .ui-state-error
{
padding: 4px;
}
.portlet
{
padding: 4px 8px;
}
.portlet-header
{
padding: 4px;
margin-bottom: 6px;
}
</style>
<script src="/Scripts/Jquery/jquery-1.3.1.js" type="text/javascript"></script>
<script src="/Scripts/Jquery/ui/ui.core.js" type="text/javascript"></script>
<script src="/Scripts/Jquery/ui/ui.draggable.js" type="text/javascript"></script>
<script src="/Scripts/Jquery/ui/ui.resizable.js" type="text/javascript"></script>
<script src="/Scripts/Jquery/ui/ui.dialog.js" type="text/javascript"></script>
<script type="text/javascript" src="/Scripts/Jquery/ui/effects.core.js"></script>
<script type="text/javascript" src="/Scripts/Jquery/ui/effects.highlight.js"></script>
<script type="text/javascript" src="/Scripts/Jquery/external/bgiframe/jquery.bgiframe.js"></script>
现在我们要做的是捕获传统的form的post, 让它以ajax的方式提交.

第一步是收集要post的数据.于是我们写下以下JavaScript代码,为了方便,我加在jQuery的全局函数中了..

jQuery.otisAjax = {
getPostData: function(FromID) {
var ob = new Object();
$(FromID + " :input").each(function(i) {
ob[$(this).attr("name")] = $(this).val();
});
return { data: ob, action: $(FromID).attr("action"), method: $(FromID).attr("method") };
},
returnType: { text: "text", html: "html", script: "script", json: "json" },
post: function(FromID, callback, rType) {
var pInfo = this.getPostData(FromID);
$.post(pInfo.action, pInfo.data, callback, rType == undefined ? this.returnType.html : rType);
}
};

jQuery.otisAjax.getPostData的功能是捕获包含在form中的所有要Post出去的数据,并抓取要Post到的URL和method. Jquery的强大的选择功能,可以很轻松地做到.

jQuery.otisAjax.post的功能是简单地调用一下jQuery.post.

OK,好了. 现在开始构建对话框并实现ajax提交. 以下是全部代码.

 $(function() {
$("#createCategories").dialog({
bgiframe: true,
autoOpen: false,
modal: true,
buttons: {
'新建分类': function() {
$.otisAjax.post("#frm-CreateCategories",
function(data, textStatus) {
alert(data); if (textStatus == "success") { $("#createCategories").dialog('close'); getTree(); } // $("#createCategories").dialog('close');
}, "text");
},
'取消': function() {
$(this).dialog('close');
}
}
});
$("#btn-createCategories").click(function() {
$("#createCategories").dialog('open');
});

});

 

这就是带Ajax功能的简单的增加数据的全部代码. 因为是Demo,所以少考虑了N种情况.可以看出这种做法非常地简单,非常方便..


下载地址;http://files.cnblogs.com/OtisBlog/OtisMVCBlog.rar

 

 

[SQLServer]SQL自定义函数

mikel阅读(781)

用户自定义函数(User Defined Functions)是SQL Server 的数据库对象,它不能用于执行一系列改变数据库状态的操作,但它可以像系统函数一样在查询或存储过程等的程序段中使用,也可以像存储过程一样通过EXECUTE 命令来执行。用户自定义函数中存储了一个Transact-SQL 例程,可以返回一定的值。

  在SQL Server 中根据函数返回值形式的不同将用户自定义函数分为三种类型:

  标量型函数(Scalar functions

  标量型函数返回一个确定类型的标量值其返回值类型为除TEXT NTEXT IMAGECURSOR TIMESTAMP TABLE 类型外的其它数据类型。函数体语句定义在BEGIN-END语句内,其中包含了可以返回值的Transact-SQL 命令。

  内联表值型函数(Inline table-valued functions

  内联表值型函数以表的形式返回一个返回值,即它返回的是一个表内联表值型函数没有由BEGIN-END 语句括起来的函数体。其返回的表由一个位于RETURN 子句中的Select 命令段从数据库中筛选出来。内联表值型函数功能相当于一个参数化的视图。

  多声明表值型函数(Multi-statement table-valued functions

  多声明表值型函数可以看作标量型和内联表值型函数的结合体。它的返回值是一个表,但它和标量型函数一样有一个用BEGIN-END 语句括起来的函数体,返回值的表中的数据是由函数体中的语句插入的。由此可见,它可以进行多次查询,对数据进行多次筛选与合并,弥补了内联表值型函数的不足。  

  SQL Server 为三种类型的用户自定义函数提供了不同的命令创建格式。

  (1 创建标量型用户自定义函数(Scalar functions 其语法如下:

  

  各参数说明如下:

  owner_name 指定用户自定义函数的所有者。 

  function_name:指定用户自定义函数的名称。database_name.owner_name.function_name 应是惟一的。 

  @parameter_name:定义一个或多个参数的名称。一个函数最多可以定义1024 个参数每个参数前用“@”符号标明。参数的作用范围是整个函数。参数只能替代常量,不能替代表名、列名或其它数据库对象的名称。用户自定义函数不支持输出参数。  

  scalar_parameter_data_type:指定标量型参数的数据类型,可以为除TEXT NTEXT IMAGE CURSORTIMESTAMP TABLE 类型外的其它数据类型。  

  scalar_return_data_type:指定标量型返回值的数据类型,可以为除TEXT NTEXT IMAGE CURSORTIMESTAMP TABLE 类型外的其它数据类型。  

  scalar_expression:指定标量型用户自定义函数返回的标量值表达式。 

  function_body:指定一系列的Transact-SQL 语句,它们决定了函数的返回值。  

  ENCRYPTION:加密选项。让SQL Server 对系统表中有关Create FUNCTION 的声明加密,以防止用户自定义函数作为SQL Server 复制的一部分被发布(Publish  

   SCHEMABINDING:计划绑定选项将用户自定义函数绑定到它所引用的数据库对象如果指定了此选项,则函数所涉及的数据库对象从此将不能被删除或修改,除非函数被删除或去掉此选项。应注意的是,要绑定的数据库对象必须与函数在同一数据库中。  

 

  (2创建内联表值型用户自定义函数(Inline Table-valued Functions

其语法如下:

  

  各参数说明如下:

  TABLE:指定返回值为一个表。

  select-stmt:单个Select 语句,确定返回的表的数据。

  其余参数与标量型用户自定义函数相同。

  

 

  (3 创建多声明表值型用户自定义函数

  其语法如下:

  

  各参数说明如下:

  @return_variable 一个TABLE 类型的变量,用于存储和累积返回的表中的数据行。 其余参数与标量型用户自定义函数相同。

  在多声明表值型用户自定义函数的函数体中允许使用下列Transact-SQL 语句。 赋值语句(Assignment statements); 流程控制语句(Control-of-Flow statements); 定义作用范围在函数内的变量和游标的DECLARE 语句; Select 语句; 编辑函数中定义的表变量的Insert Update Delete 语句; 在函数中允许涉及诸如声明游标、打开游标、关闭游标、释放游标这样的游标操作,对于读取游标而言,除非在FETCH 语句中使用INTO 从句来对某一变量赋值,否则不允许在函数中使用FETCH 语句来向客户端返回数据。此外不确定性函数(Non-deterministic functions 不能在用户自定义函数中使用。所谓不确定性函数是指那些使用相同的调用参数在不同时刻调用得到的返回值不同的函数。这些函数如表13-3 所示(全局变量也可以视为一种函数)。

  

[C#]Fast Reflection Library

mikel阅读(998)

全文英文版:Fast Reflection Library

  这是我在CodePlex上创建的一个项目,它的网址是http://www.codeplex.com/FastReflectionLib,使用Microsoft Public License (Ms-PL),您可以随意在自己的产品中使用它的全部或部分代码。这个项目用到了我在《方法的直接调用,反射调用与Lambda表达式调用》和《这下没理由嫌Eval的性能差了吧?》两篇文章里用到的做法,并加以提炼和扩展发布的项目——随便搞搞,留个印记,也供以后参考。

基本使用方式

   反射是.NET中非常重要的功能。使用反射来构造对象、调用方法或是访问属性是某些项目中常用的做法之一(例如ORM框架)。众所周知,与一个成员的直 接访问相比,反射调用的性能要低好几个数量级。FastReflectionLib提供了一种简便的方式,使一些常用反射调用的性能得到大幅提高。如下:

using System;
using System.Reflection;
using FastReflectionLib;
namespace SimpleConsole
{
class Program
{
static void Main(string[] args)
{
PropertyInfo propertyInfo = typeof(string).GetProperty("Length");
MethodInfo methodInfo = typeof(string).GetMethod("Contains");
string s = "Hello World!";
// get value by normal reflection
int length1 = (int)propertyInfo.GetValue(s, null);
// get value by the extension method from FastReflectionLib,
// which is much faster
int length2 = (int)propertyInfo.FastGetValue(s);
// invoke by normal reflection
bool result1 = (bool)methodInfo.Invoke(s, new object[] { "Hello" });
// invoke by the extension method from FastReflectionLib,
// which is much faster
bool result2 = (bool)methodInfo.FastInvoke(s, new object[] { "Hello" });
}
}
}

  在得到了PropertyInfo或MethodInfo对象之后,我们可以使用GetValue或Invoke方法来访问属性或调用方法。在 FastReflectionLib中为PropertyInfo、MethodInfo等对象定义了对应的扩展方法,于是我们就可以使用这些扩展方法 (从代码上看来,基本上只是在原来的方法之前加上“Fast”)来进行调用,与之前的方法相比,新的扩展方法性能有极大的提高。

直接使用各工作对象

  各FastXxx方法实际上是将PropertyInfo等对象作为Key去一个Cache中获取对应的工作对象,然后调用工作对象上对应的方法。因此,直接调用工作对象可以获得更好的性能。各工作对象类型的对应关系如下:

  • PropertyInfo:IPropertyAccessor
  • MethodInfo:IMethodInvoker
  • ConstructorInfo:IConstructorInvoker
  • FieldInfo:IFieldAccessor

  我们可以使用FastReflectionCaches.MethodInvokerCache来获取一个IMethodInvoker对象:

static void Execute(MethodInfo methodInfo, object instance, int times)
{
IMethodInvoker invoker = FastReflectionCaches.MethodInvokerCache.Get(methodInfo);
object[] parameters = new object[0];
for (int i = 0; i < times; i++)
{
invoker.Invoke(instance, parameters);
}
}

工作对象的默认实现与扩展

  在FastReflectionLib中,已经提供了IPropertyAccessor等接口的默认实现。该实现将会构造一颗表达式树 (Expression Tree)并将其编译(调用其Compile方法)以获得一个与反射方法签名相同的委托对象。这是一种简单、通用而安全的实现,由于Compile方法使 用了Emit,其性能也较为令人满意(可见下面的性能测试)。但是这并不是性能最高的做法,如果使用Emit生成最优化的代码,其性能甚至会高于方法的直 接调用(例如Dynamic Reflection Library)。如果您想使用更好的实现来替换,则可以自行构造一个工作对象接口的实现,并替换对应的Factory:

public class BetterPropertyAccessor : IPropertyAccessor
{
public BetterPropertyAccessor(PropertyInfo propertyInfo) { ... }
...
}
public class BetterPropertyAccessorFactory :
IFastReflectionFactory<PropertyInfo, IPropertyAccessor>
{
public IPropertyAccessor Create(PropertyInfo key)
{
return new BetterPropertyAccessor(key);
}
}
class Program
{
static void Main(string[] args)
{
FastReflectionFactories.PropertyAccessorFactory =
new BetterPropertyAccessorFactory();
...
}
}

缓存的默认实现与扩展

  在FastReflectionLib中使用基于 System.Collections.Generic.Dictionary<TKey, TValue>类型编写的缓存容器。每次调用FastXxx扩展方法时,类库将从对应的缓存容器中获取工作对象。如果缓存容器中还没有所需的工作对 象,那么它就会调用合适的Factory来构造新的工作对象。从下面的性能测试来看,许多时间是消耗在缓存查找上的,如果您有更好的缓存实现,可以使用以 下的方法替换默认的缓存的容器:

public class BetterMethodInvokerCache :
IFastReflectionCache<MethodInfo, IMethodInvoker>
{
public IMethodInvoker Get(MethodInfo key) { ... }
}
class Program
{
static void Main(string[] args)
{
FastReflectionCaches.MethodInvokerCache =
new BetterMethodInvokerCache();
...
}
}

根据需要自行缓存工作对象

  FastReflectionLib中通过PropertyInfo等对象作为Key,对PropertyAccessor等工作对象进行缓 存。但是在某些场景下,您也可以选择合适的方式来自行缓存工作对象。与FastReflectionLib源码同时发布的CustomCache示例网站 中包含了一个FastEval扩展,在某些场景下,我们可以使用这个更高效的方法来替换内置的Eval方法。这个示例的特点如下:

  • 使用对象的类型和属性名同时作为缓存的Key获取对应的PropertyAccessor对象
  • 使用PropertyAccessor获取“匿名对象”中的属性值
  • 缓存的作用域为特定页面,而不是整个AppDomain。

性能测试

  FastReflectionLib源码中包含了一个性能测试项目,您可以从中看出FastReflectionLib对于反射的性能改进。摘录部分数据如下(测试在我的笔记本上运行,Release编译)。

  执行以下方法:

public class Test
{
public void MethodWithArgs(int a1, string a2) { }
}

  进行一百万次调用,结果如下:

调用方式 消耗时间(秒)
方法直接调用 0.0071397
内置反射调用 1.4936181
工作对象调用 0.0468326
Fast方法调用 0.1373712

[Lucene] Lucene.net多字段(Fields)、多索引目录(IndexSearcher

mikel阅读(567)

Lucene.net是目前在.net环境中被普遍使用的全文索引的开源项目,这次在项目的开发中也使用它进行全文索引。
在开发过程中碰到一些小问题就是对多字段和多索引目录进行搜索。
1、多字段搜索就是同时要一个以上的字段中的内容进行比较搜索,类似概念在SQL中就是select * from Table where a like '%query%' or b like '%query%'。
Lucene.net中的单个字段查询大家都比较熟悉,这里对字段content进行搜索
Query query = QueryParser.Parse(querystr,"content",new ChineseAnalyzer());
Hits hits = searcher.Search(query);
对多个字段查询用到一个MultiFieldQueryParser对象,该对象继承自Query,我们要对字段title,content进行搜索。
string[] fields = {"content","title"};
Query multiquery = MultiFieldQueryParser.Parse(querystr,fields,new ChineseAnalyzer());
Hits hits = searcher.Search(multiquery);
2、多索引目录就是要在多个索引目录的中进行比较搜索,类似概念在SQL中就是select * from TableA union select * from TableB。
IndexSearcher[] searchers = new IndexSearcher[2];
searchers[0] = new IndexSearcher(IndexPath0);
searchers[1] = new IndexSearcher(IndexPath1);
MultiSearcher multisearcher = new MultiSearcher(searchers);
TopDocs multitopdocs = multisearcher.Search(query, null, 1000);
这个搜索的结果可能有相同的信息,比如你有一条相同的信息在多个目录中索引,搜索的结果就会出现多次相同的信息。
还有一种搜索方式是用到ParallelMultiSearcher这个对象,它是从MulitSearcher继承而来。
ParallelMultiSearcher parallelmultisearcher = new ParallelMultiSearcher(searchers);
TopDocs paralleltopdocs = parallelmultisearcher.Search(query, null, 1000);
这个搜索是对搜索后的结果进行合并,剔除重复的信息。