寫了個通用的比較器(comparer),應用动态生成Lambda(调用属性及方法)

最近在用Linq的Distinct ,Except等方法是,遇到一個問題,就是這些方法都需要一個比較器才能跑出想要的東西

所以每當類型不同時都要自己寫個比較器,這樣下來一樣project下就會有好幾個比較器

所以我在想有沒有辦法寫一個通用的比較器呢?通過查詢學習,終於寫出了一個通用的比較器.

 

代碼如下:

 

 

ExpandedBlockStart.gif 代码
     public   class  CommComparer < T >  : IEqualityComparer < T > //  where T : struct,IQueryable  // IComparable, IConvertible, IFormattable
    {
        
private  Func < T, T,  bool >  equals;
        
private  Func < T,  int >  getHashCode;
        
private   string  _propName;

        
public  CommComparer( string  prop1)
        {
            _propName 
=  prop1;
            getHashCode 
=  generateGetHashCode();
            equals 
=  generateEquals();
        }
        
public  CommComparer()
        {
            getHashCode 
=  generateGetHashCode();
            equals 
=  generateEquals();
        }
        
public   bool  Equals(T x, T y)
        {
            
return  equals(x, y);
        }
        
public   int  GetHashCode(T obj)
        {
            
return  getHashCode(obj);
        }

        
private  Func < T, T,  bool >  generateEquals()
        {
            var xParam 
=  Expression.Parameter( typeof (T),  " x " );
            var yParam 
=  Expression.Parameter( typeof (T),  " y " );
            var getHashCodeMethod 
=   typeof (T).GetMethod( " GetHashCode " );
            
switch  ( typeof (T).Name)
            {
                
case   " DataRow " :
                    Func
< ParameterExpression, MethodCallExpression >  func  =  (param)  =>
                    {
                        var fieldMethod 
=   typeof (DataRowExtensions).GetMethods().First(m  =>  m.Name  ==   " Field "   &&
                            m.IsGenericMethod).MakeGenericMethod(
typeof ( object ));
                        var valueExpr 
=  Expression.Constant(_propName,  typeof ( string ));
                        var methodCallExpr 
=  Expression.Call( null , fieldMethod,  new  Expression[] { param, valueExpr });
                        
return  methodCallExpr;
                    };
                    var xMethod 
=  func(xParam);
                    var yMethod 
=  func(yParam);
                    var equalExpression 
=  Expression.Equal(Expression.Call(xMethod, getHashCodeMethod), Expression.Call(yMethod, getHashCodeMethod));
                    
return  Expression.Lambda < Func < T, T,  bool >> (equalExpression,  new [] { xParam, yParam }).Compile();
                    
break ;
                
default :
                    
if  ( string .IsNullOrEmpty(_propName))
                    {
                        equalExpression 
=  Expression.Equal(Expression.Call(xParam, getHashCodeMethod), Expression.Call(yParam, getHashCodeMethod));
                        
return  Expression.Lambda < Func < T, T,  bool >> (equalExpression,  new [] { xParam, yParam }).Compile();
                    }
                    
else
                    {
                        var xPropExpr 
=  Expression.Property(xParam, _propName);
                        var yPropExpr 
=  Expression.Property(yParam, _propName);
                        equalExpression 
=  Expression.Equal(Expression.Call(xPropExpr, getHashCodeMethod), Expression.Call(yPropExpr, getHashCodeMethod));
                        
return  Expression.Lambda < Func < T, T,  bool >> (equalExpression,  new [] { xParam, yParam }).Compile();
                    }
                    
break ;
            }
        }

        
private  Func < T,  int >  generateGetHashCode()
        {
            var objParam 
=  Expression.Parameter( typeof (T),  " obj " );
            
switch  ( typeof (T).Name)
            {
                
case   " DataRow " :
                    Func
< ParameterExpression, MethodCallExpression >  func  =  (param)  =>
                    {
                        var fieldMethod 
=   typeof (DataRowExtensions).GetMethods().First(m  =>  m.Name  ==   " Field "   &&
                            m.IsGenericMethod).MakeGenericMethod(
typeof ( object ));
                        var valueExpr 
=  Expression.Constant(_propName,  typeof ( string ));
                        var methodCallExpr 
=  Expression.Call(param, fieldMethod,  new  Expression[] { param, valueExpr });
                        
return  methodCallExpr;
                    };
                    var method 
=  func(objParam);
                    var underlyingType 
=  method.Type;
                    var getHashCodeMethod 
=  underlyingType.GetMethod( " GetHashCode " );
                    var getHashCodeExpression 
=  Expression.Call(method, getHashCodeMethod);
                    
return  Expression.Lambda < Func < T,  int >> (getHashCodeExpression,  new [] { objParam }).Compile();
                    
break ;
                
default :
                    
if  ( string .IsNullOrEmpty(_propName))
                    {
                        underlyingType 
=  objParam.Type;
                        getHashCodeMethod 
=  underlyingType.GetMethod( " GetHashCode " );
                        getHashCodeExpression 
=  Expression.Call(objParam, getHashCodeMethod);
                        
return  Expression.Lambda < Func < T,  int >> (getHashCodeExpression,  new [] { objParam }).Compile();
                    }
                    
else
                    {
                        var objParamProp 
=  Expression.Property(objParam, _propName);
                        underlyingType 
=  objParamProp.Type;
                        getHashCodeMethod 
=  underlyingType.GetMethod( " GetHashCode " );
                        getHashCodeExpression 
=  Expression.Call(objParamProp, getHashCodeMethod);
                        
return  Expression.Lambda < Func < T,  int >> (getHashCodeExpression,  new [] { objParam }).Compile();
                    }
                    
break ;
            }
        }
    }

 

調用方法如下:

1.對於control的比較,如果用ID來做比較,則代碼如下:

這個是屬性的調用方法:

ExpandedBlockStart.gif 代码
 IEnumerable < WizardStepBase >  differenceSteps  =  wizard1.WizardSteps.Cast < WizardStepBase > ().Except(wizard2.WizardSteps.Cast < WizardStepBase > (),
                    
new  CommComparer < WizardStepBase > ( " ID " ));

 

 

2.如果比較的是DataRow ,而且比較的字段是"HIERARCHYNAME",則代碼如下:

那這個是方法的調用方法了.

var r  in  dt.AsEnumerable().Distinct( new  CommComparer < DataRow > ( " HIERARCHYNAME " ))

 

 

這個比較器目前只滿足了我的需求,可能不完善,大家可以自己發揮,我只是拋磚引玉的作用吧

 

 

转载于:https://www.cnblogs.com/zzyyll2/archive/2010/01/08/1642653.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值