Esempio n. 1
0
 public void Load(MethodEmitter method)
 {
     if (m_Field != null)
     {
         method.LoadArgument(0);
         method.LoadField(m_Field);
     }
     else if (m_Value == null)
     {
         method.LoadNull(m_Type);
     }
     else
     {
         if (m_Value is int)
         {
             method.Load((int)m_Value);
         }
         else if (m_Value is long)
         {
             method.Load((long)m_Value);
         }
         else if (m_Value is float)
         {
             method.Load((float)m_Value);
         }
         else if (m_Value is double)
         {
             method.Load((double)m_Value);
         }
         else if (m_Value is char)
         {
             method.Load((char)m_Value);
         }
         else if (m_Value is bool)
         {
             method.Load((bool)m_Value);
         }
         else if (m_Value is string)
         {
             method.Load((string)m_Value);
         }
         else if (m_Value is Enum)
         {
             method.Load((Enum)m_Value);
         }
         else if (m_Value is uint)
         {
             method.Load((long)m_Value);
         }
         else
         {
             throw new InvalidOperationException("Unrecognized comparison value.");
         }
     }
 }
Esempio n. 2
0
 public void Load(MethodEmitter method)
 {
     if (Field != null)
     {
         method.LoadArgument(0);
         method.LoadField(Field);
     }
     else if (Value == null)
     {
         method.LoadNull(Type);
     }
     else
     {
         if (Value is int i)
         {
             method.Load(i);
         }
         else if (Value is long l)
         {
             method.Load(l);
         }
         else if (Value is float f)
         {
             method.Load(f);
         }
         else if (Value is double d)
         {
             method.Load(d);
         }
         else if (Value is char c)
         {
             method.Load(c);
         }
         else if (Value is bool b)
         {
             method.Load(b);
         }
         else if (Value is string s)
         {
             method.Load(s);
         }
         else if (Value is Enum e)
         {
             method.Load(e);
         }
         else
         {
             throw new InvalidOperationException("Unrecognized comparison value.");
         }
     }
 }
 public void Load(MethodEmitter method)
 {
     if (m_Field != null)
     {
         method.LoadArgument(0);
         method.LoadField(m_Field);
     }
     else if (m_Value == null)
     {
         method.LoadNull(m_Type);
     }
     else
     {
         if (m_Value is int i)
         {
             method.Load(i);
         }
         else if (m_Value is long lValue)
         {
             method.Load(lValue);
         }
         else if (m_Value is float fValue)
         {
             method.Load(fValue);
         }
         else if (m_Value is double dValue)
         {
             method.Load(dValue);
         }
         else if (m_Value is char cValue)
         {
             method.Load(cValue);
         }
         else if (m_Value is bool bValue)
         {
             method.Load(bValue);
         }
         else if (m_Value is string sValue)
         {
             method.Load(sValue);
         }
         else if (m_Value is Enum eValue)
         {
             method.Load(eValue);
         }
         else
         {
             throw new InvalidOperationException("Unrecognized comparison value.");
         }
     }
 }
Esempio n. 4
0
        public override void Compile(MethodEmitter emitter)
        {
            emitter.Chain(m_Property);

            bool inverse = false;

            bool couldCompare =
                emitter.CompareTo(1, () => { m_Value.Load(emitter); });

            if (couldCompare)
            {
                emitter.Load(0);

                switch (m_Operator)
                {
                case ComparisonOperator.Equal:
                    emitter.Compare(OpCodes.Ceq);
                    break;

                case ComparisonOperator.NotEqual:
                    emitter.Compare(OpCodes.Ceq);
                    inverse = true;
                    break;

                case ComparisonOperator.Greater:
                    emitter.Compare(OpCodes.Cgt);
                    break;

                case ComparisonOperator.GreaterEqual:
                    emitter.Compare(OpCodes.Clt);
                    inverse = true;
                    break;

                case ComparisonOperator.Lesser:
                    emitter.Compare(OpCodes.Clt);
                    break;

                case ComparisonOperator.LesserEqual:
                    emitter.Compare(OpCodes.Cgt);
                    inverse = true;
                    break;

                default:
                    throw new InvalidOperationException("Invalid comparison operator.");
                }
            }
            else
            {
                // This type is -not- comparable
                // We can only support == and != operations

                m_Value.Load(emitter);

                switch (m_Operator)
                {
                case ComparisonOperator.Equal:
                    emitter.Compare(OpCodes.Ceq);
                    break;

                case ComparisonOperator.NotEqual:
                    emitter.Compare(OpCodes.Ceq);
                    inverse = true;
                    break;

                case ComparisonOperator.Greater:
                case ComparisonOperator.GreaterEqual:
                case ComparisonOperator.Lesser:
                case ComparisonOperator.LesserEqual:
                    throw new InvalidOperationException("Property does not support relational comparisons.");

                default:
                    throw new InvalidOperationException("Invalid operator.");
                }
            }

            if (m_Not != inverse)
            {
                emitter.LogicalNot();
            }
        }
Esempio n. 5
0
        public override void Compile(MethodEmitter emitter)
        {
            bool inverse = false;

            string methodName;

            switch (m_Operator)
            {
            case StringOperator.Equal:
                methodName = "Equals";
                break;

            case StringOperator.NotEqual:
                methodName = "Equals";
                inverse    = true;
                break;

            case StringOperator.Contains:
                methodName = "Contains";
                break;

            case StringOperator.StartsWith:
                methodName = "StartsWith";
                break;

            case StringOperator.EndsWith:
                methodName = "EndsWith";
                break;

            default:
                throw new InvalidOperationException("Invalid string comparison operator.");
            }

            if (m_IgnoreCase || methodName == "Equals")
            {
                Type type = m_IgnoreCase ? typeof(InsensitiveStringHelpers) : typeof(string);

                emitter.BeginCall(
                    type.GetMethod(
                        methodName,
                        BindingFlags.Public | BindingFlags.Static,
                        null,
                        new[]
                {
                    typeof(string),
                    typeof(string)
                },
                        null));

                emitter.Chain(m_Property);
                m_Value.Load(emitter);

                emitter.FinishCall();
            }
            else
            {
                Label notNull = emitter.CreateLabel();
                Label moveOn  = emitter.CreateLabel();

                LocalBuilder temp = emitter.AcquireTemp(m_Property.Type);

                emitter.Chain(m_Property);

                emitter.StoreLocal(temp);
                emitter.LoadLocal(temp);

                emitter.BranchIfTrue(notNull);

                emitter.Load(false);
                emitter.Pop();
                emitter.Branch(moveOn);

                emitter.MarkLabel(notNull);
                emitter.LoadLocal(temp);

                emitter.BeginCall(
                    typeof(string).GetMethod(
                        methodName,
                        BindingFlags.Public | BindingFlags.Instance,
                        null,
                        new[]
                {
                    typeof(string)
                },
                        null));

                m_Value.Load(emitter);

                emitter.FinishCall();

                emitter.MarkLabel(moveOn);
            }

            if (m_Not != inverse)
            {
                emitter.LogicalNot();
            }
        }
Esempio n. 6
0
        public static IComparer Compile(AssemblyEmitter assembly, Type objectType, OrderInfo[] orders)
        {
            TypeBuilder typeBuilder = assembly.DefineType(
                "__sort",
                TypeAttributes.Public,
                typeof(object));

            #region Constructor
            {
                ConstructorBuilder ctor = typeBuilder.DefineConstructor(
                    MethodAttributes.Public,
                    CallingConventions.Standard,
                    Type.EmptyTypes);

                ILGenerator il = ctor.GetILGenerator();

                // : base()
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));

                // return;
                il.Emit(OpCodes.Ret);
            }
            #endregion

            #region IComparer
            typeBuilder.AddInterfaceImplementation(typeof(IComparer));

            MethodBuilder compareMethod;

            #region Compare
            {
                MethodEmitter emitter = new MethodEmitter(typeBuilder);

                emitter.Define(
                    /*  name  */ "Compare",
                    /*  attr  */ MethodAttributes.Public | MethodAttributes.Virtual,
                    /* return */ typeof(int),
                    /* params */ new Type[] { typeof(object), typeof(object) });

                LocalBuilder a = emitter.CreateLocal(objectType);
                LocalBuilder b = emitter.CreateLocal(objectType);

                LocalBuilder v = emitter.CreateLocal(typeof(int));

                emitter.LoadArgument(1);
                emitter.CastAs(objectType);
                emitter.StoreLocal(a);

                emitter.LoadArgument(2);
                emitter.CastAs(objectType);
                emitter.StoreLocal(b);

                emitter.Load(0);
                emitter.StoreLocal(v);

                Label end = emitter.CreateLabel();

                for (int i = 0; i < orders.Length; ++i)
                {
                    if (i > 0)
                    {
                        emitter.LoadLocal(v);
                        emitter.BranchIfTrue(end); // if ( v != 0 ) return v;
                    }

                    OrderInfo orderInfo = orders[i];

                    Property prop = orderInfo.Property;
                    int sign = orderInfo.Sign;

                    emitter.LoadLocal(a);
                    emitter.Chain(prop);

                    bool couldCompare =
                        emitter.CompareTo(sign, delegate()
                        {
                            emitter.LoadLocal(b);
                            emitter.Chain(prop);
                        });

                    if (!couldCompare)
                        throw new InvalidOperationException("Property is not comparable.");

                    emitter.StoreLocal(v);
                }

                emitter.MarkLabel(end);

                emitter.LoadLocal(v);
                emitter.Return();

                typeBuilder.DefineMethodOverride(
                    emitter.Method,
                    typeof(IComparer).GetMethod(
                        "Compare",
                        new Type[]
                        {
                            typeof(object),
                            typeof(object)
                        }));

                compareMethod = emitter.Method;
            }
            #endregion
            #endregion

            Type comparerType = typeBuilder.CreateType();

            return (IComparer)Activator.CreateInstance(comparerType);
        }
        public static IComparer Compile(AssemblyEmitter assembly, Type objectType, Property[] props)
        {
            TypeBuilder typeBuilder = assembly.DefineType(
                "__distinct",
                TypeAttributes.Public,
                typeof(object)
                );

            #region Constructor
            {
                ConstructorBuilder ctor = typeBuilder.DefineConstructor(
                    MethodAttributes.Public,
                    CallingConventions.Standard,
                    Type.EmptyTypes
                    );

                ILGenerator il = ctor.GetILGenerator();

                // : base()
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));

                // return;
                il.Emit(OpCodes.Ret);
            }
            #endregion

            #region IComparer
            typeBuilder.AddInterfaceImplementation(typeof(IComparer));

            MethodBuilder compareMethod;

            #region Compare
            {
                MethodEmitter emitter = new MethodEmitter(typeBuilder);

                emitter.Define(
                    /*  name  */ "Compare",
                    /*  attr  */ MethodAttributes.Public | MethodAttributes.Virtual,
                    /* return */ typeof(int),
                    /* params */ new Type[] { typeof(object), typeof(object) });

                LocalBuilder a = emitter.CreateLocal(objectType);
                LocalBuilder b = emitter.CreateLocal(objectType);

                LocalBuilder v = emitter.CreateLocal(typeof(int));

                emitter.LoadArgument(1);
                emitter.CastAs(objectType);
                emitter.StoreLocal(a);

                emitter.LoadArgument(2);
                emitter.CastAs(objectType);
                emitter.StoreLocal(b);

                emitter.Load(0);
                emitter.StoreLocal(v);

                Label end = emitter.CreateLabel();

                for (int i = 0; i < props.Length; ++i)
                {
                    if (i > 0)
                    {
                        emitter.LoadLocal(v);
                        emitter.BranchIfTrue(end);                           // if ( v != 0 ) return v;
                    }

                    Property prop = props[i];

                    emitter.LoadLocal(a);
                    emitter.Chain(prop);

                    bool couldCompare =
                        emitter.CompareTo(1, delegate()
                    {
                        emitter.LoadLocal(b);
                        emitter.Chain(prop);
                    });

                    if (!couldCompare)
                    {
                        throw new InvalidOperationException("Property is not comparable.");
                    }

                    emitter.StoreLocal(v);
                }

                emitter.MarkLabel(end);

                emitter.LoadLocal(v);
                emitter.Return();

                typeBuilder.DefineMethodOverride(
                    emitter.Method,
                    typeof(IComparer).GetMethod(
                        "Compare",
                        new Type[]
                {
                    typeof(object),
                    typeof(object)
                }
                        )
                    );

                compareMethod = emitter.Method;
            }
            #endregion
            #endregion

            #region IEqualityComparer
            typeBuilder.AddInterfaceImplementation(typeof(IEqualityComparer <object>));

            #region Equals
            {
                MethodEmitter emitter = new MethodEmitter(typeBuilder);

                emitter.Define(
                    /*  name  */ "Equals",
                    /*  attr  */ MethodAttributes.Public | MethodAttributes.Virtual,
                    /* return */ typeof(bool),
                    /* params */ new Type[] { typeof(object), typeof(object) });

                emitter.Generator.Emit(OpCodes.Ldarg_0);
                emitter.Generator.Emit(OpCodes.Ldarg_1);
                emitter.Generator.Emit(OpCodes.Ldarg_2);

                emitter.Generator.Emit(OpCodes.Call, compareMethod);

                emitter.Generator.Emit(OpCodes.Ldc_I4_0);

                emitter.Generator.Emit(OpCodes.Ceq);

                emitter.Generator.Emit(OpCodes.Ret);

                typeBuilder.DefineMethodOverride(
                    emitter.Method,
                    typeof(IEqualityComparer <object>).GetMethod(
                        "Equals",
                        new Type[]
                {
                    typeof(object),
                    typeof(object)
                }
                        )
                    );
            }
            #endregion

            #region GetHashCode
            {
                MethodEmitter emitter = new MethodEmitter(typeBuilder);

                emitter.Define(
                    /*  name  */ "GetHashCode",
                    /*  attr  */ MethodAttributes.Public | MethodAttributes.Virtual,
                    /* return */ typeof(int),
                    /* params */ new Type[] { typeof(object) });

                LocalBuilder obj = emitter.CreateLocal(objectType);

                emitter.LoadArgument(1);
                emitter.CastAs(objectType);
                emitter.StoreLocal(obj);

                for (int i = 0; i < props.Length; ++i)
                {
                    Property prop = props[i];

                    emitter.LoadLocal(obj);
                    emitter.Chain(prop);

                    Type active = emitter.Active;

                    MethodInfo getHashCode = active.GetMethod("GetHashCode", Type.EmptyTypes);

                    if (getHashCode == null)
                    {
                        getHashCode = typeof(object).GetMethod("GetHashCode", Type.EmptyTypes);
                    }

                    if (active != typeof(int))
                    {
                        if (!active.IsValueType)
                        {
                            LocalBuilder value = emitter.AcquireTemp(active);

                            Label valueNotNull = emitter.CreateLabel();
                            Label done         = emitter.CreateLabel();

                            emitter.StoreLocal(value);
                            emitter.LoadLocal(value);

                            emitter.BranchIfTrue(valueNotNull);

                            emitter.Load(0);
                            emitter.Pop(typeof(int));

                            emitter.Branch(done);

                            emitter.MarkLabel(valueNotNull);

                            emitter.LoadLocal(value);
                            emitter.Call(getHashCode);

                            emitter.ReleaseTemp(value);

                            emitter.MarkLabel(done);
                        }
                        else
                        {
                            emitter.Call(getHashCode);
                        }
                    }

                    if (i > 0)
                    {
                        emitter.Xor();
                    }
                }

                emitter.Return();

                typeBuilder.DefineMethodOverride(
                    emitter.Method,
                    typeof(IEqualityComparer <object>).GetMethod(
                        "GetHashCode",
                        new Type[]
                {
                    typeof(object)
                }
                        )
                    );
            }
            #endregion
            #endregion

            Type comparerType = typeBuilder.CreateType();

            return((IComparer)Activator.CreateInstance(comparerType));
        }
Esempio n. 8
0
        public static IComparer Compile(AssemblyEmitter assembly, Type objectType, OrderInfo[] orders)
        {
            TypeBuilder typeBuilder = assembly.DefineType(
                "__sort",
                TypeAttributes.Public,
                typeof(object));

            #region Constructor
            {
                ConstructorBuilder ctor = typeBuilder.DefineConstructor(
                    MethodAttributes.Public,
                    CallingConventions.Standard,
                    Type.EmptyTypes);

                ILGenerator il = ctor.GetILGenerator();

                // : base()
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));

                // return;
                il.Emit(OpCodes.Ret);
            }
            #endregion

            #region IComparer
            typeBuilder.AddInterfaceImplementation(typeof(IComparer));

            MethodBuilder compareMethod;

            #region Compare
            {
                MethodEmitter emitter = new MethodEmitter(typeBuilder);

                emitter.Define(
                    /*  name  */ "Compare",
                    /*  attr  */ MethodAttributes.Public | MethodAttributes.Virtual,
                    /* return */ typeof(int),
                    /* params */ new Type[] { typeof(object), typeof(object) });

                LocalBuilder a = emitter.CreateLocal(objectType);
                LocalBuilder b = emitter.CreateLocal(objectType);

                LocalBuilder v = emitter.CreateLocal(typeof(int));

                emitter.LoadArgument(1);
                emitter.CastAs(objectType);
                emitter.StoreLocal(a);

                emitter.LoadArgument(2);
                emitter.CastAs(objectType);
                emitter.StoreLocal(b);

                emitter.Load(0);
                emitter.StoreLocal(v);

                Label end = emitter.CreateLabel();

                for (int i = 0; i < orders.Length; ++i)
                {
                    if (i > 0)
                    {
                        emitter.LoadLocal(v);
                        emitter.BranchIfTrue(end); // if ( v != 0 ) return v;
                    }

                    OrderInfo orderInfo = orders[i];

                    Property prop = orderInfo.Property;
                    int      sign = orderInfo.Sign;

                    emitter.LoadLocal(a);
                    emitter.Chain(prop);

                    bool couldCompare =
                        emitter.CompareTo(sign, delegate()
                    {
                        emitter.LoadLocal(b);
                        emitter.Chain(prop);
                    });

                    if (!couldCompare)
                    {
                        throw new InvalidOperationException("Property is not comparable.");
                    }

                    emitter.StoreLocal(v);
                }

                emitter.MarkLabel(end);

                emitter.LoadLocal(v);
                emitter.Return();

                typeBuilder.DefineMethodOverride(
                    emitter.Method,
                    typeof(IComparer).GetMethod(
                        "Compare",
                        new Type[]
                {
                    typeof(object),
                    typeof(object)
                }));

                compareMethod = emitter.Method;
            }
            #endregion
            #endregion

            Type comparerType = typeBuilder.CreateType();

            return((IComparer)Activator.CreateInstance(comparerType));
        }
Esempio n. 9
0
        public static IComparer <T> Compile <T>(AssemblyEmitter assembly, Type objectType, Property[] props)
        {
            var typeBuilder = assembly.DefineType(
                "__distinct",
                TypeAttributes.Public,
                typeof(object)
                );

            {
                var ctor = typeBuilder.DefineConstructor(
                    MethodAttributes.Public,
                    CallingConventions.Standard,
                    Type.EmptyTypes
                    );

                var il = ctor.GetILGenerator();

                // : base()
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(
                    OpCodes.Call,
                    typeof(T).GetConstructor(Type.EmptyTypes) ??
                    throw new Exception($"Could not find empty constructor for type {typeof(T).FullName}")
                    );

                // return;
                il.Emit(OpCodes.Ret);
            }

            typeBuilder.AddInterfaceImplementation(typeof(IComparer <T>));

            MethodBuilder compareMethod;

            {
                var emitter = new MethodEmitter(typeBuilder);

                emitter.Define(
                    /*  name  */ "Compare",
                    /*  attr  */
                    MethodAttributes.Public | MethodAttributes.Virtual,
                    /* return */
                    typeof(int),
                    /* params */
                    new[] { typeof(T), typeof(T) }
                    );

                var a = emitter.CreateLocal(objectType);
                var b = emitter.CreateLocal(objectType);

                var v = emitter.CreateLocal(typeof(int));

                emitter.LoadArgument(1);
                emitter.CastAs(objectType);
                emitter.StoreLocal(a);

                emitter.LoadArgument(2);
                emitter.CastAs(objectType);
                emitter.StoreLocal(b);

                emitter.Load(0);
                emitter.StoreLocal(v);

                var end = emitter.CreateLabel();

                for (var i = 0; i < props.Length; ++i)
                {
                    if (i > 0)
                    {
                        emitter.LoadLocal(v);
                        emitter.BranchIfTrue(end);
                    }

                    var prop = props[i];

                    emitter.LoadLocal(a);
                    emitter.Chain(prop);

                    var couldCompare =
                        emitter.CompareTo(
                            1,
                            () =>
                    {
                        emitter.LoadLocal(b);
                        emitter.Chain(prop);
                    }
                            );

                    if (!couldCompare)
                    {
                        throw new InvalidOperationException("Property is not comparable.");
                    }

                    emitter.StoreLocal(v);
                }

                emitter.MarkLabel(end);

                emitter.LoadLocal(v);
                emitter.Return();

                typeBuilder.DefineMethodOverride(
                    emitter.Method,
                    typeof(IComparer <T>).GetMethod(
                        "Compare",
                        new[]
                {
                    typeof(T),
                    typeof(T)
                }
                        ) ?? throw new Exception($"No Compare method found for type {typeof(T).FullName}")
                    );

                compareMethod = emitter.Method;
            }

            typeBuilder.AddInterfaceImplementation(typeof(IEqualityComparer <T>));
            {
                var emitter = new MethodEmitter(typeBuilder);

                emitter.Define(
                    /*  name  */ "Equals",
                    /*  attr  */
                    MethodAttributes.Public | MethodAttributes.Virtual,
                    /* return */
                    typeof(bool),
                    /* params */
                    new[] { typeof(T), typeof(T) }
                    );

                emitter.Generator.Emit(OpCodes.Ldarg_0);
                emitter.Generator.Emit(OpCodes.Ldarg_1);
                emitter.Generator.Emit(OpCodes.Ldarg_2);

                emitter.Generator.Emit(OpCodes.Call, compareMethod);

                emitter.Generator.Emit(OpCodes.Ldc_I4_0);

                emitter.Generator.Emit(OpCodes.Ceq);

                emitter.Generator.Emit(OpCodes.Ret);

                typeBuilder.DefineMethodOverride(
                    emitter.Method,
                    typeof(IEqualityComparer <T>).GetMethod(
                        "Equals",
                        new[]
                {
                    typeof(T),
                    typeof(T)
                }
                        ) ?? throw new Exception($"No Equals method found for type {typeof(T).FullName}")
                    );
            }

            {
                var emitter = new MethodEmitter(typeBuilder);

                emitter.Define(
                    /*  name  */ "GetHashCode",
                    /*  attr  */
                    MethodAttributes.Public | MethodAttributes.Virtual,
                    /* return */
                    typeof(int),
                    /* params */
                    new[] { typeof(T) }
                    );

                var obj = emitter.CreateLocal(objectType);

                emitter.LoadArgument(1);
                emitter.CastAs(objectType);
                emitter.StoreLocal(obj);

                for (var i = 0; i < props.Length; ++i)
                {
                    var prop = props[i];

                    emitter.LoadLocal(obj);
                    emitter.Chain(prop);

                    var active = emitter.Active;

                    var getHashCode = active.GetMethod("GetHashCode", Type.EmptyTypes);

                    getHashCode ??= typeof(T).GetMethod("GetHashCode", Type.EmptyTypes);

                    if (active != typeof(int))
                    {
                        if (!active.IsValueType)
                        {
                            var value = emitter.AcquireTemp(active);

                            var valueNotNull = emitter.CreateLabel();
                            var done         = emitter.CreateLabel();

                            emitter.StoreLocal(value);
                            emitter.LoadLocal(value);

                            emitter.BranchIfTrue(valueNotNull);

                            emitter.Load(0);
                            emitter.Pop(typeof(int));

                            emitter.Branch(done);

                            emitter.MarkLabel(valueNotNull);

                            emitter.LoadLocal(value);
                            emitter.Call(getHashCode);

                            emitter.ReleaseTemp(value);

                            emitter.MarkLabel(done);
                        }
                        else
                        {
                            emitter.Call(getHashCode);
                        }
                    }

                    if (i > 0)
                    {
                        emitter.Xor();
                    }
                }

                emitter.Return();

                typeBuilder.DefineMethodOverride(
                    emitter.Method,
                    typeof(IEqualityComparer <T>).GetMethod(
                        "GetHashCode",
                        new[]
                {
                    typeof(T)
                }
                        ) ?? throw new Exception($"No GetHashCode method found for type {typeof(T).FullName}")
                    );
            }

            var comparerType = typeBuilder.CreateType();

            return(comparerType.CreateInstance <IComparer <T> >());
        }
		public void Load( MethodEmitter method )
		{
			if ( m_Field != null )
			{
				method.LoadArgument( 0 );
				method.LoadField( m_Field );
			}
			else if ( m_Value == null )
			{
				method.LoadNull( m_Type );
			}
			else
			{
				if ( m_Value is int )
					method.Load( (int) m_Value );
				else if ( m_Value is long )
					method.Load( (long) m_Value );
				else if ( m_Value is float )
					method.Load( (float) m_Value );
				else if ( m_Value is double )
					method.Load( (double) m_Value );
				else if ( m_Value is char )
					method.Load( (char) m_Value );
				else if ( m_Value is bool )
					method.Load( (bool) m_Value );
				else if ( m_Value is string )
					method.Load( (string) m_Value );
				else if ( m_Value is Enum )
					method.Load( (Enum) m_Value );
				else
					throw new InvalidOperationException( "Unrecognized comparison value." );
			}
		}
		public override void Compile( MethodEmitter emitter )
		{
			emitter.Chain( m_Property );

			bool inverse = false;

			bool couldCompare =
			emitter.CompareTo( 1, delegate()
			{
				m_Value.Load( emitter );
			} );

			if ( couldCompare )
			{
				emitter.Load( 0 );

				switch ( m_Operator )
				{
					case ComparisonOperator.Equal:
						emitter.Compare( OpCodes.Ceq );
						break;

					case ComparisonOperator.NotEqual:
						emitter.Compare( OpCodes.Ceq );
						inverse = true;
						break;

					case ComparisonOperator.Greater:
						emitter.Compare( OpCodes.Cgt );
						break;

					case ComparisonOperator.GreaterEqual:
						emitter.Compare( OpCodes.Clt );
						inverse = true;
						break;

					case ComparisonOperator.Lesser:
						emitter.Compare( OpCodes.Clt );
						break;

					case ComparisonOperator.LesserEqual:
						emitter.Compare( OpCodes.Cgt );
						inverse = true;
						break;

					default:
						throw new InvalidOperationException( "Invalid comparison operator." );
				}
			}
			else
			{
				// This type is -not- comparable
				// We can only support == and != operations

				m_Value.Load( emitter );

				switch ( m_Operator )
				{
					case ComparisonOperator.Equal:
						emitter.Compare( OpCodes.Ceq );
						break;

					case ComparisonOperator.NotEqual:
						emitter.Compare( OpCodes.Ceq );
						inverse = true;
						break;

					case ComparisonOperator.Greater:
					case ComparisonOperator.GreaterEqual:
					case ComparisonOperator.Lesser:
					case ComparisonOperator.LesserEqual:
						throw new InvalidOperationException( "Property does not support relational comparisons." );

					default:
						throw new InvalidOperationException( "Invalid operator." );
				}
			}

			if ( m_Not != inverse )
				emitter.LogicalNot();
		}
		public override void Compile( MethodEmitter emitter )
		{
			bool inverse = false;

			string methodName;

			switch ( m_Operator )
			{
				case StringOperator.Equal:
					methodName = "Equals";
					break;

				case StringOperator.NotEqual:
					methodName = "Equals";
					inverse = true;
					break;

				case StringOperator.Contains:
					methodName = "Contains";
					break;

				case StringOperator.StartsWith:
					methodName = "StartsWith";
					break;

				case StringOperator.EndsWith:
					methodName = "EndsWith";
					break;

				default:
					throw new InvalidOperationException( "Invalid string comparison operator." );
			}

			if ( m_IgnoreCase || methodName == "Equals" )
			{
				Type type = ( m_IgnoreCase ? typeof( Insensitive ) : typeof( String ) );

				emitter.BeginCall(
					type.GetMethod(
						methodName,
						BindingFlags.Public | BindingFlags.Static,
						null,
						new Type[]
						{
							typeof( string ),
							typeof( string )
						},
						null
					)
				);

				emitter.Chain( m_Property );
				m_Value.Load( emitter );

				emitter.FinishCall();
			}
			else
			{
				Label notNull = emitter.CreateLabel();
				Label moveOn = emitter.CreateLabel();

				LocalBuilder temp = emitter.AcquireTemp( m_Property.Type );

				emitter.Chain( m_Property );

				emitter.StoreLocal( temp );
				emitter.LoadLocal( temp );

				emitter.BranchIfTrue( notNull );

				emitter.Load( false );
				emitter.Pop();
				emitter.Branch( moveOn );

				emitter.MarkLabel( notNull );
				emitter.LoadLocal( temp );

				emitter.BeginCall(
					typeof( string ).GetMethod(
						methodName,
						BindingFlags.Public | BindingFlags.Instance,
						null,
						new Type[]
						{
							typeof( string )
						},
						null
					)
				);

				m_Value.Load( emitter );

				emitter.FinishCall();

				emitter.MarkLabel( moveOn );
			}

			if ( m_Not != inverse )
				emitter.LogicalNot();
		}
Esempio n. 13
0
        public static IComparer Compile(AssemblyEmitter assembly, Type objectType, Property[] props)
        {
            TypeBuilder typeBuilder = assembly.DefineType(
                "__distinct",
                TypeAttributes.Public,
                typeof(object));

            #region Constructor
            {
                ConstructorBuilder ctor = typeBuilder.DefineConstructor(
                    MethodAttributes.Public,
                    CallingConventions.Standard,
                    Type.EmptyTypes);

                ILGenerator il = ctor.GetILGenerator();

                // : base()
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes));

                // return;
                il.Emit(OpCodes.Ret);
            }
            #endregion

            #region IComparer
            typeBuilder.AddInterfaceImplementation(typeof(IComparer));

            MethodBuilder compareMethod;

            #region Compare
            {
                MethodEmitter emitter = new MethodEmitter(typeBuilder);

                emitter.Define(
                    /*  name  */ "Compare",
                    /*  attr  */ MethodAttributes.Public | MethodAttributes.Virtual,
                    /* return */ typeof(int),
                    /* params */ new Type[] { typeof(object), typeof(object) });

                LocalBuilder a = emitter.CreateLocal(objectType);
                LocalBuilder b = emitter.CreateLocal(objectType);

                LocalBuilder v = emitter.CreateLocal(typeof(int));

                emitter.LoadArgument(1);
                emitter.CastAs(objectType);
                emitter.StoreLocal(a);

                emitter.LoadArgument(2);
                emitter.CastAs(objectType);
                emitter.StoreLocal(b);

                emitter.Load(0);
                emitter.StoreLocal(v);

                Label end = emitter.CreateLabel();

                for (int i = 0; i < props.Length; ++i)
                {
                    if (i > 0)
                    {
                        emitter.LoadLocal(v);
                        emitter.BranchIfTrue(end); // if ( v != 0 ) return v;
                    }

                    Property prop = props[i];

                    emitter.LoadLocal(a);
                    emitter.Chain(prop);

                    bool couldCompare =
                        emitter.CompareTo(1, delegate()
                        {
                            emitter.LoadLocal(b);
                            emitter.Chain(prop);
                        });

                    if (!couldCompare)
                        throw new InvalidOperationException("Property is not comparable.");

                    emitter.StoreLocal(v);
                }

                emitter.MarkLabel(end);

                emitter.LoadLocal(v);
                emitter.Return();

                typeBuilder.DefineMethodOverride(
                    emitter.Method,
                    typeof(IComparer).GetMethod(
                        "Compare",
                        new Type[]
                        {
                            typeof(object),
                            typeof(object)
                        }));

                compareMethod = emitter.Method;
            }
            #endregion
            #endregion

            #region IEqualityComparer
            typeBuilder.AddInterfaceImplementation(typeof(IEqualityComparer<object>));

            #region Equals
            {
                MethodEmitter emitter = new MethodEmitter(typeBuilder);

                emitter.Define(
                    /*  name  */ "Equals",
                    /*  attr  */ MethodAttributes.Public | MethodAttributes.Virtual,
                    /* return */ typeof(bool),
                    /* params */ new Type[] { typeof(object), typeof(object) });

                emitter.Generator.Emit(OpCodes.Ldarg_0);
                emitter.Generator.Emit(OpCodes.Ldarg_1);
                emitter.Generator.Emit(OpCodes.Ldarg_2);

                emitter.Generator.Emit(OpCodes.Call, compareMethod);

                emitter.Generator.Emit(OpCodes.Ldc_I4_0);

                emitter.Generator.Emit(OpCodes.Ceq);

                emitter.Generator.Emit(OpCodes.Ret);

                typeBuilder.DefineMethodOverride(
                    emitter.Method,
                    typeof(IEqualityComparer<object>).GetMethod(
                        "Equals",
                        new Type[]
                        {
                            typeof(object),
                            typeof(object)
                        }));
            }
            #endregion

            #region GetHashCode
            {
                MethodEmitter emitter = new MethodEmitter(typeBuilder);

                emitter.Define(
                    /*  name  */ "GetHashCode",
                    /*  attr  */ MethodAttributes.Public | MethodAttributes.Virtual,
                    /* return */ typeof(int),
                    /* params */ new Type[] { typeof(object) });

                LocalBuilder obj = emitter.CreateLocal(objectType);

                emitter.LoadArgument(1);
                emitter.CastAs(objectType);
                emitter.StoreLocal(obj);

                for (int i = 0; i < props.Length; ++i)
                {
                    Property prop = props[i];

                    emitter.LoadLocal(obj);
                    emitter.Chain(prop);

                    Type active = emitter.Active;

                    MethodInfo getHashCode = active.GetMethod("GetHashCode", Type.EmptyTypes);

                    if (getHashCode == null)
                        getHashCode = typeof(object).GetMethod("GetHashCode", Type.EmptyTypes);

                    if (active != typeof(int))
                    {
                        if (!active.IsValueType)
                        {
                            LocalBuilder value = emitter.AcquireTemp(active);

                            Label valueNotNull = emitter.CreateLabel();
                            Label done = emitter.CreateLabel();

                            emitter.StoreLocal(value);
                            emitter.LoadLocal(value);

                            emitter.BranchIfTrue(valueNotNull);

                            emitter.Load(0);
                            emitter.Pop(typeof(int));

                            emitter.Branch(done);

                            emitter.MarkLabel(valueNotNull);

                            emitter.LoadLocal(value);
                            emitter.Call(getHashCode);

                            emitter.ReleaseTemp(value);

                            emitter.MarkLabel(done);
                        }
                        else
                        {
                            emitter.Call(getHashCode);
                        }
                    }

                    if (i > 0)
                        emitter.Xor();
                }

                emitter.Return();

                typeBuilder.DefineMethodOverride(
                    emitter.Method,
                    typeof(IEqualityComparer<object>).GetMethod(
                        "GetHashCode",
                        new Type[]
                        {
                            typeof(object)
                        }));
            }
            #endregion
            #endregion

            Type comparerType = typeBuilder.CreateType();

            return (IComparer)Activator.CreateInstance(comparerType);
        }