示例#1
0
 public FieldHasher(PropertyInfo[] props, FieldHasherOptions options)
 {
     this.Props = props;
     this.expr  = CreateExpression(props, options);
 }
示例#2
0
        private Func <T1, int> CreateExpression(PropertyInfo[] fields, FieldHasherOptions options)
        {
            /*
             * $hash = 17;
             * $hash += $hash * 23 + .Call ($obj.a).GetHashCode();
             * $hash += $hash * 23 + .Call ($obj.b).GetHashCode();
             * .If ($obj.s != null) {
             *  $hash += $hash * 23 + .Call (.Call ($obj.s).Trim()).GetHashCode()
             * } .Else {
             *  $hash *= 23
             * };
             * $hash += $hash * 23 + .Call ($obj.date).GetHashCode();
             * $hash += $hash * 23 + .Call ($obj.mynullable).GetHashCode();
             * $hash
             */
            const int prim       = 17;
            const int prim2      = 23;
            var       t1param    = EE.Param <T1>("obj");
            var       resultHash = EE.Param <int>("hash");
            var       ass        = Expression.Assign(resultHash, Expression.Constant(prim));
            var       block      = new List <Expression>();

            block.Add(ass);
            var returnLabel = Expression.Label(typeof(int));

            var whenNull = options.ZeroIfNulls ? Expression.Return(returnLabel, Expression.Constant(0))
                : resultHash.MulAssign(prim2);

            block.AddRange(fields.Select(pi =>
            {
                var dotted   = t1param.Dot(pi.Name);
                var propType = pi.PropertyType;

                var addAssignHashCode = Expression.AddAssign(resultHash,
                                                             resultHash.Mul(prim2).Add(dotted.Call("GetHashCode")));

                // nullable
                if (options.ZeroIfNulls && Nullable.GetUnderlyingType(propType) != null)
                {
                    return(Expression.IfThenElse(
                               dotted.NotNull(),
                               addAssignHashCode,
                               whenNull));
                }

                // value type but not nullabl
                if (propType.IsValueType)
                {
                    return((Expression)addAssignHashCode);
                }


                // normalized string
                var normalized = propType == typeof(string) && options.StringNormalizer != null
                    ? options.StringNormalizer(dotted)
                    : dotted;

                var iffed = Expression.IfThenElse(dotted.NotNull(),
                                                  Expression.AddAssign(resultHash,
                                                                       resultHash.Mul(prim2).Add(normalized.Call("GetHashCode"))),
                                                  whenNull);

                return(iffed);
            }));

            block.Add(Expression.Label(returnLabel, resultHash));
            var eblock = Expression.Block(new [] { resultHash }, block);
            var l      = Expression.Lambda <Func <T1, int> >(eblock, t1param);

            return(l.Compile());
        }