private static Hasher BuildDynamicHasher(Type declaringType, IReadOnlyCollection <FieldInfo> fieldInfos)
        {
            return(DynamicMethod <Hasher> .New(il =>
            {
                // Declare the local variable to store the target instance
                il.DeclareLocal(declaringType);

                // Load the argument (the object instance)
                il.Emit(OpCodes.Ldarg_1);
                il.Emit(OpCodes.Castclass, declaringType);
                il.Emit(OpCodes.Stloc_0);

                // Unroll the member access
                MethodInfo
                validateDelegateInfo = typeof(ShaderHashCodeProvider).GetMethod(nameof(ValidateDelegate), BindingFlags.NonPublic | BindingFlags.Static),
                getMethodInfo = typeof(Delegate).GetProperty(nameof(Delegate.Method)).GetMethod,
                getHashCodeInfo = typeof(object).GetMethod(nameof(GetHashCode));
                foreach (FieldInfo fieldInfo in fieldInfos)
                {
                    Label label = il.DefineLabel();

                    // if (fieldInfo.GetValue(obj) != null) {
                    il.Emit(OpCodes.Ldloc_0);
                    il.Emit(OpCodes.Ldfld, fieldInfo);
                    il.Emit(OpCodes.Brfalse_S, label);

                    // if (ValidateDelegate(field)) {
                    il.Emit(OpCodes.Ldloc_0);
                    il.Emit(OpCodes.Ldfld, fieldInfo);
                    il.EmitCall(OpCodes.Call, validateDelegateInfo, null);
                    il.Emit(OpCodes.Brfalse_S, label);

                    // hash = hash * 17 + field.Method.GetHashCode();
                    il.Emit(OpCodes.Ldarg_0);
                    il.Emit(OpCodes.Ldc_I4_S, (byte)17);
                    il.Emit(OpCodes.Mul);
                    il.Emit(OpCodes.Ldloc_0);
                    il.Emit(OpCodes.Ldfld, fieldInfo);
                    il.EmitCall(OpCodes.Callvirt, getMethodInfo, null);
                    il.EmitCall(OpCodes.Callvirt, getHashCodeInfo, null);
                    il.Emit(OpCodes.Add);
                    il.Emit(OpCodes.Starg_S, (byte)0);

                    il.MarkLabel(label);
                }

                // Return the computed hash
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ret);
            }));
        }
Beispiel #2
0
        public void TestSquare()
        {
            Square square = DynamicMethod <Square> .New(il =>
            {
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Dup);
                il.Emit(OpCodes.Mul);
                il.Emit(OpCodes.Ret);
            });

            int result = square(2); // result = 2 * 2

            Assert.IsTrue(result == 4);
        }