views:

228

answers:

2

I'm wondering if there is an equivalent function to PHP's call_user_func() in ASP.NET application. I'm looking to do a conversion from a PHP application to ASP.NET as a means of teaching myself the language, by taking a CMS I built professionally and trying to recreate it in this other language.

The reason I need a function similar to this, is because the current structure of my PHP CMS involves a plugin architecture, and specific parts of the CMS expose themselves for the plugins, and it then handles the returned information as an array. It's pretty much the same system Drupal uses.

Am I perhaps on the wrong track with this?

I think for clarification I should provide an example of how this works in my current system:

<?php
class Test {

    function TestMessage() {
        // set up array
        $arrTest = array("Hello", "World");
        // get extra values from all available plugins
        $arrExtras = CMS::InvokeHook("HelloTest");
        // now contains Hello, World, Foo, Bar
        $arrTests = array_merge($arrTest, $arrExtras);
    }

}

class CMS {
    InvokeHook($function) {
        // now contains a couple plugins
        $plugins = CMS::GetPlugins();
        // empty array of values
        $values = array();
        foreach($plugins as $plugin) {
            // if this plugin has the called method...
            if(method_exists($plugin, $function)) {
                // call the function and merge in the results
                $values[] = call_user_func(array($plugin, $function));
            }
        }
        // return results as an array
        return $values;
    }
}

class FooTest {
    function HelloTest() {
        return "Foo";
    }
}

class BarTest {
    function HelloTest() {
        return "Bar";
    }
}

?>

NOTE: The InvokeHook() call is simplified as I'm writing this from memory, but that is the gist of it.

A: 

To the .NET devs, this is basically a method of calling a method from a given name (as a string).

To the OP: (I think) You have to use reflection. It's nowhere near as pretty and it's quite expensive (IIRC) so it's best not over-used.

System.Reflection.MethodInfo method = this.GetType().GetMethod(myMethodName);
// method.Invoke(args, null);

I think you might possibly be doing things the "wrong" way if you have to resort to this to get things done. There's possible a cleaner pattern that will work better.

The way I've made plugin-architectures is through globally shared interfaces* so plugins can implement a "plug-in" interface* and then I know there is going to be a .DoSomething() (etc) method available. No reflection needed =)

*Or Abstract Classes.. Really, whatever fits best!

Oli
+3  A: 

In .NET I would probably create some events and handle them. Here's one way of doing it:

public class CMS

    public Event DoSomethingHook(byval sender as Object, byval e as DoSomethingEventArgs)

    public function DoSomething()
     dim data() as Integer = {} 
     Dim e as new DoSomethingEventArgs();
     e.data = data
     RaiseEvent DoSomethingHook(Me, e)
     data = e.data
    end function
end class


' Let's say Plugin base class contains a reference to CMS
public class CMSPlugin
    Inherits Plugin 

    public sub New()
     ' Register for a hook
     AddHandler CMS.DoSomethingHook, AddressOf DoSomething
    end sub

    public function DoSomething(byval sender as Object, byval e as DoSomethingEventArgs)
     ' Do something with e.data
    end function
end class

public class DoSomethingEventArgs : Inherits EventArgs
    public data() as Integer
end class
Kevin