2002-08-21 Dietmar Maurer <dietmar@ximian.com>
[mono.git] / mcs / class / corlib / System / Delegate.cs
index 9ae8063528529707aae1b850729e8c120d7e1f72..8320f380cd9c9c7e641a818c9f58ee98be40faad 100644 (file)
 //
 // Author:
 //   Miguel de Icaza (miguel@ximian.com)
+//   Daniel Stodden (stodden@in.tum.de)
+//   Dietmar Maurer (dietmar@ximian.com)
 //
 // (C) Ximian, Inc.  http://www.ximian.com
 //
-// TODO:  Mucho left to implement
-//
 
 using System;
+using System.Globalization;
+using System.Reflection;
 using System.Runtime.Serialization;
+using System.Runtime.CompilerServices;
+
 
 namespace System {
 
+       [MonoTODO]
        public abstract class Delegate : ICloneable, ISerializable {
                protected Type target_type;
-               protected object target;
-               protected string method;
-               
+               protected object m_target;
+               protected string method_name;
+               protected IntPtr method_ptr;
+               protected IntPtr delegate_trampoline;
+               protected MethodInfo method_info;
+
                protected Delegate (object target, string method)
                {
                        if (target == null)
-                               throw new ArgumentNullException ("Target object is null");
+                               throw new ArgumentNullException (Locale.GetText ("Target object is null"));
 
                        if (method == null)
-                               throw new ArgumentNullException ("method name is null");
+                               throw new ArgumentNullException (Locale.GetText ("method name is null"));
 
                        this.target_type = null;
-                       this.target = target;
-                       this.method = method;
+                       this.method_ptr = IntPtr.Zero;
+                       this.m_target = target;
+                       this.method_name = method;
                }
 
                protected Delegate (Type target_type, string method)
                {
-                       if (target == null)
-                               throw new ArgumentNullException ("Target type is null");
+                       if (m_target == null)
+                               throw new ArgumentNullException (Locale.GetText ("Target type is null"));
 
                        if (method == null)
-                               throw new ArgumentNullException ("method string is null");
+                               throw new ArgumentNullException (Locale.GetText ("method string is null"));
 
                        this.target_type = target_type;
-                       this.target = null;
-                       this.method = method;
+                       this.method_ptr = IntPtr.Zero;
+                       this.m_target = null;
+                       this.method_name = method;
                }
 
-#if NOTYET
                public MethodInfo Method {
                        get {
-                               return null;
+                               return method_info;
                        }
                }
-#endif
 
                public object Target {
                        get {
-                               return target;
+                               return m_target;
                        }
                }
 
-
                //
                // Methods
                //
 
-               public abstract object Clone ();
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               internal static extern Delegate CreateDelegate_internal (Type type, object target, MethodInfo info);
+
+               public static Delegate CreateDelegate (Type type, MethodInfo info)
+               {
+                       if (type == null)
+                               throw new ArgumentNullException (Locale.GetText ("Type is null"));
+
+                       if (info == null)
+                               throw new ArgumentNullException (Locale.GetText ("MethodInfo is null"));
+
+                       return CreateDelegate_internal (type, null, info);
+               }
+               
+               public static Delegate CreateDelegate (Type type, object target, string method)
+               {
+                       if (type == null)
+                               throw new ArgumentNullException (Locale.GetText ("Type is null"));
+
+                       if (target == null)
+                               throw new ArgumentNullException (Locale.GetText ("Target object is null"));
+
+                       if (method == null)
+                               throw new ArgumentNullException (Locale.GetText ("method string is null"));
+
+                       BindingFlags flags =  BindingFlags.Public | BindingFlags.Instance;
+                       MethodInfo info = target.GetType ().GetMethod (method, flags);
+                       return CreateDelegate_internal (type, target, info);
+               }
+
+               public static Delegate CreateDelegate (Type type, Type target, string method)
+               {
+                       if (type == null)
+                               throw new ArgumentNullException (Locale.GetText ("Type is null"));
+
+                       if (target == null)
+                               throw new ArgumentNullException (Locale.GetText ("Target type is null"));
+
+                       if (method == null)
+                               throw new ArgumentNullException (Locale.GetText ("method string is null"));
+
+                       BindingFlags flags =  BindingFlags.Public | BindingFlags.Static;
+                       MethodInfo info = target.GetMethod (method, flags);
+                       return CreateDelegate_internal (type, null, info);
+               }
+
+               public static Delegate CreateDelegate (Type type, object target, string method, bool ignorecase)
+               {
+                       if (type == null)
+                               throw new ArgumentNullException (Locale.GetText ("Type is null"));
+
+                       if (target == null)
+                               throw new ArgumentNullException (Locale.GetText ("Target object is null"));
+
+                       if (method == null)
+                               throw new ArgumentNullException (Locale.GetText ("method string is null"));
+                       
+                       Type target_type = target.GetType ();
+                       BindingFlags flags =  BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase;
+                       MethodInfo info = target_type.GetMethod (method, flags);
+                       return CreateDelegate_internal (type, target, info);                    
+               }
+
+               public object DynamicInvoke( object[] args )
+               {
+                       return DynamicInvokeImpl( args );
+               }
+
+               public virtual object DynamicInvokeImpl( object[] args )
+               {
+                       if (Method == null) {
+                               Type[] mtypes = new Type [args.Length];
+                               for (int i = 0; i < args.Length; ++i) {
+                               mtypes [i] = args [i].GetType ();
+                       }
+                               method_info = m_target.GetType ().GetMethod (method_name, mtypes);
+                       }
+                       return Method.Invoke( m_target, args );
+               }
+
+               public virtual object Clone()
+               {
+                       return MemberwiseClone();
+               }
 
                public override bool Equals (object o)
                {
-                       if (!(o is System.Delegate))
+                       if ( o == null )
                                return false;
-
-                       Delegate d = (Delegate) o;
                        
+                       Delegate d = (Delegate) o;
                        if ((d.target_type == target_type) &&
-                           (d.target == target) &&
-                           (d.method == method))
+                           (d.m_target == m_target) &&
+                           (d.method_name == method_name) &&
+                           (d.method_ptr == method_ptr))
                                return true;
 
                        return false;
@@ -83,14 +173,91 @@ namespace System {
 
                public override int GetHashCode ()
                {
-                       return method.GetHashCode ();
+                       return (int)method_ptr;
                }
 
                // This is from ISerializable
+               [MonoTODO]
                public void GetObjectData (SerializationInfo info, StreamingContext context)
                {
                        // TODO: IMPLEMENT ME
                }
+
+               public virtual Delegate[] GetInvocationList()
+               {
+                       return new Delegate[] { this };
+               }
+
+               /// <symmary>
+               ///   Returns a new MulticastDelegate holding the
+               ///   concatenated invocation lists of MulticastDelegates a and b
+               /// </symmary>
+               public static Delegate Combine (Delegate a, Delegate b)
+               {
+                       if (a == null){
+                               if (b == null)
+                                       return null;
+                               return b;
+                       } else 
+                               if (b == null)
+                                       return a;
+
+                       if (a.GetType () != b.GetType ())
+                               throw new ArgumentException (Locale.GetText ("Incompatible Delegate Types"));
+                       
+                       return a.CombineImpl (b);
+               }
+
+               /// <symmary>
+               ///   Returns a new MulticastDelegate holding the
+               ///   concatenated invocation lists of an Array of MulticastDelegates
+               /// </symmary>
+               public static Delegate Combine( Delegate[] delegates )
+               {
+                       Delegate retval = null;
+
+                       foreach ( Delegate next in delegates )
+                               retval = Combine( retval, next );
+
+                       return retval;
+               }
+
+
+               protected virtual Delegate CombineImpl (Delegate d)
+               {
+                       throw new MulticastNotSupportedException ("");
+               }
+               
                
+               public static Delegate Remove( Delegate source, Delegate value ) 
+               {
+                       if ( source == null )
+                               return null;
+                               
+                       return source.RemoveImpl( value );
+               }
+
+               protected virtual Delegate RemoveImpl( Delegate d )
+               {
+                       if ( this.Equals( d ) )
+                               return null;
+                      
+                       return this;
+               }
+
+               public static bool operator ==( Delegate a, Delegate b )
+               {
+                       if ((object)a == null) {
+                               if ((object)b == null)
+                                       return true;
+                               return false;
+                       }
+                       return a.Equals( b );
+               }
+
+               public static bool operator !=( Delegate a, Delegate b )
+               {
+                       return !(a == b);
+               }
        }
 }