Robin Rodricks
Robin Rodricks

Reputation: 113996

Extension method for methods do not show in IntelliSense

How do I create an extension method that can execute a given function later? I've come up with the following code, but it doesn't list in the IntelliSense list when you type MyFunc.DoLater().

I've declared the extension method in a static class...

using TTimer = System.Timers.Timer; // to prevent confusion with Windows.Forms.Timer

public static void DoLater(this Action handler, int delay) {
    TTimer timer = new TTimer(delay);
    timer.Elapsed += delegate {
       handler();
       timer.Dispose();
    };
    timer.Start();
}

... and MyFunc is just a method in a Form class with no parameters.

public void MyFunc(){
}

Upvotes: 3

Views: 1141

Answers (3)

Hand-E-Food
Hand-E-Food

Reputation: 12794

Cast the method as an Action.

((Action)MyMethod).DoLater(10000);

To use the extension method, the compiler is expecting an object of type Action. I'm not entirely sure what the difference between a method member and an Action member is, but I'm guessing there's an explicit conversion from method to Action.

Upvotes: 1

Jürgen Steinblock
Jürgen Steinblock

Reputation: 31743

You need an action instance to execute your extension method on:

var a = new Action(() => MyFunc());
a.DoLater();

But I would suggest a better and more generic approach:

public static class DoLaterExtension
{
    public static void DoLater<T>(this T x, int delay, Action<T> action)
    {
        // TODO: Impelement timer logic
        action.Invoke(x);
    }
}

private void Example()
{
    var instance = new MyForm();
    instance.DoLater(1000, x => x.MyFunc());
}

Keep in mind that you should better use a System.Windows.Fomrs.Timer to avoid thread issues. Or the TPL way (if you are on .net 4.0 i would suggest that).

public static void DoLater<T>(this T x, int delay, Action<T> action)
{
    var scheduler = TaskScheduler.FromCurrentSynchronizationContext();
    Task.Factory.StartNew(() =>
    {
        System.Threading.Thread.Sleep(delay);   
    }).ContinueWith(t =>
    {
        action.Invoke(x);
    }, scheduler);
}

And if you use .net 4.5 you can even use Task.Delay http://msdn.microsoft.com/en-us/library/hh194845.aspx

Upvotes: 3

Fredrik
Fredrik

Reputation: 2317

Nice idea. I tried it using System.Timers.Timer and it works fine.

static class Program
{
    static System.Timers.Timer _timer;

    static void Main(string[] args)
    {
        DoLater(SayHello, 5000);
        Console.ReadLine();
    }

    public static void DoLater(this Action handler, int delay)
    {
        _timer = new System.Timers.Timer(delay);
        _timer.Elapsed += new ElapsedEventHandler(delegate {
                                   handler();
                                   _timer.Dispose();
                                });
        _timer.Enabled = true;
    }

    public static void SayHello()
    {
        MessageBox.Show("Hello World");
    }
}

Upvotes: 1

Related Questions