Share via


Methods as objects, again

Suppose we continue along the same lines, but with methods.  I want to make a class that represents a method.

 

There are several problems I ran in to:

 

  1. You can’t constrain a type parameter to System.Delegate.  It’s just not allowed.
  2. I can’t make the Invoke method have the right signature.  It’s just not possible.
  3. I can’t provide an conversion from the method to the proper delegate type (see below why that would be nice)

 

Here’s what I came up with.  It’s not ideal, but I was able to make a lot of progress.

 

      // Note: really I want to be generic, but you can't constrain to a delegate

      // type. For the purpose of this exercise, I'm using a concrete type

      // instead

      delegate void T(string s);

      class Method //<T> where T : Delegate

      {

            public readonly T Value;

            bool _isExecuting = false;

            public bool IsExecuting { get { return _isExecuting; } }

            public StartEndEvent StartEndEvent;

            private Method()

            {

                  StartEndEvent.OnStart += delegate { this._isExecuting = true; };

                  StartEndEvent.OnEnd += delegate { this._isExecuting = false; };

            }

            public Method(T t) : this() { this.Value = t; }

            public object Invoke(params object[] args)

            {

                  using (this.StartEndEvent.Open(this))

                  {

                        return this.Value.DynamicInvoke (args);

                  }

            }

            // these don't work because I can't match the signature.

            //public static implicit operator T(Method m) { return m.Invoke; }

            //public static implicit operator T(Method m) { return delegate { m.Invoke(); }; }

      }

      // example usage

      class C

      {

            public readonly Method Method1 = new Method(delegate(string s)

            {

                  Console.WriteLine("Method1 was called - [{0}]", s);

            });

            static void Main(string[] args)

            {

                  C c = new C();

                  c.Method1.Invoke("Method1.Invoke");

                  T t = c.Method1.Value;

                  // I really want

                  // T t = c.Method1, but the conversions won't work

                  t("via a delegate");

            }

      }

 

This should make it possible to do some AOP, since you can register events on method invocation.

 

I used the events to manage the IsExecuting state.  It’s a little funky that in your OnStart handler, the IsExecuting state may or may not be set; there’s no guarantees made.

 

You’ll need the StartEndEvent class to make this work, too.

 

I’m curious what you think.  Can we make it more elegant?  Can I make a case for allowing a System.Delegate constraint in the language?

 

Edit: fix typo in Invoke()

Comments

  • Anonymous
    June 14, 2004
    Based on this series of posts, I'd say that you are really trying to re-invent Smalltalk in C style syntax - but on top of a VM that doesn't (at least not yet) offer sufficient support for what you want. This is part of the reason that Smalltalk is very hard to implement on top of the CLR (or on top of the JVM, for that matter).
  • Anonymous
    June 14, 2004
    It would definately be nice if there were first-class support for these types of features in .Net -- .Net would truly become a language independent framework...
  • Anonymous
    June 15, 2004
    "a class that represents a method" <br>

    Have a look at S#
    http://www.refactory.com/Software/SharpSmalltalk/index.html <br>

    Look at DotNetMethod in sst.sif