动作委托引用在另一个类中?

时间:2019-03-13 11:10:13

标签: c# delegates action

我正在寻找一种方法,该方法允许另一个类通过从该类中调用一个方法来向我的Action委托添加方法,而不是在第一个类上调用Action。

这就是我需要的:

class Program
{
    static void Main(string[] args)
    {
        Action Execute = delegate { };

        ProgramTest prog = new ProgramTest(ref Execute);

        prog.AddMethod();

        Execute();
    }
}

class ProgramTest
{
    public Action execute;

    public ProgramTest(ref Action action)
    {
        execute = action;
    }

    public void AddMethod()
    {
        execute += Print;
    }

    public void Print()
    {
        Console.WriteLine("test");
        Console.ReadLine();
    }
}

但是,当我调用Execute()时,什么也没发生。

我如何使其工作?

4 个答案:

答案 0 :(得分:1)

另一种选择是将(不可变的)委托放入可变容器中。

public class ActionContainer
{
    public Action Action { get; set; } = () => { };
}

class Program
{
    static void Main(string[] args)
    {
        ActionContainer execute = new ActionContainer();

        ProgramTest prog = new ProgramTest(execute);

        prog.AddMethod();

        execute.Action();
    }
}

class ProgramTest
{
    public ActionContainer execute;

    public ProgramTest(ActionContainer action)
    {
        execute = action;
    }

    public void AddMethod()
    {
        execute.Action += Print;
    }

    public void Print()
    {
        Console.WriteLine("test");
        Console.ReadLine();
    }
}

答案 1 :(得分:0)

您想要的是什么

class Program
{
    static void Main(string[] args)
    {
        Action Execute = delegate { };

        ProgramTest prog = new ProgramTest(h => Execute += h);

        prog.AddMethod();

        Execute();
    }
}

class ProgramTest
{
    public Action<Action> execute;

    public ProgramTest(Action<Action> action)
    {
        execute = action;
    }

    public void AddMethod()
    {
        execute(Print);
    }

    public void Print()
    {
        Console.WriteLine("test");
        Console.ReadLine();
    }
}

test打印到控制台。


这是此模式的更好版本:

class Program
{
    static void Main(string[] args)
    {
        Action Execute = delegate { };

        ProgramTest prog = new ProgramTest(h => Execute += h, h => Execute -= h);

        var subscription = prog.AddMethod();

        Execute();

        subscription.Dispose();
    }
}

class ProgramTest
{
    public Action<Action> _attach;
    public Action<Action> _detach;

    public ProgramTest(Action<Action> attach, Action<Action> detach)
    {
        _attach = attach;
        _detach = detach;
    }

    public IDisposable AddMethod()
    {
        _attach(Print);
        return Disposable.Create(() => _detach(Print));
    }

    public void Print()
    {
        Console.WriteLine("test");
        Console.ReadLine();
    }
}

public sealed class Disposable : IDisposable
{
    public static IDisposable Create(Action action)
        => new Disposable(action);

    private readonly Action _action;
    private int _disposed;

    private Disposable(Action action)
    {
        _action = action;
    }

    public void Dispose()
    {
        if (Interlocked.Exchange(ref _disposed, 1) == 0)
        {
            _action();
        }
    }
}

我什至更进一步地定义了MetaAction-您可以根据需要随意传递并添加方法。

class Program
{
    static void Main(string[] args)
    {
        Action Execute = delegate { };

        MetaAction meta = MetaAction.Create(h => Execute += h, h => Execute -= h);

        var prog = new ProgramTest(meta);

        var subscription = prog.AddMethod();

        Execute();

        subscription.Dispose();
    }
}

public class MetaAction
{
    public static MetaAction Create(Action<Action> attach, Action<Action> detach)
        => new MetaAction(attach, detach);

    public Action<Action> _attach;
    public Action<Action> _detach;

    private MetaAction(Action<Action> attach, Action<Action> detach)
    {
        _attach = attach;
        _detach = detach;
    }

    public IDisposable Subscribe(Action action)
    {
        _attach(action);
        return Disposable.Create(() => _detach(action));
    }
}

public class ProgramTest
{
    public MetaAction _meta;

    public ProgramTest(MetaAction meta)
    {
        _meta = meta;
    }

    public IDisposable AddMethod()
    {
        return _meta.Subscribe(Print);
    }

    public void Print()
    {
        Console.WriteLine("test");
        Console.ReadLine();
    }
}

public sealed class Disposable : IDisposable
{
    public static IDisposable Create(Action action)
        => new Disposable(action);

    private readonly Action _action;
    private int _disposed;

    private Disposable(Action action)
    {
        _action = action;
    }

    public void Dispose()
    {
        if (Interlocked.Exchange(ref _disposed, 1) == 0)
        {
            _action();
        }
    }
}

答案 2 :(得分:0)

您可以通过调用prog.Execute而不是Execute来使其工作,就像下面的代码一样。

class Program
{
    static void Main(string[] args)
    {
        Action Execute = delegate { };
        ProgramTest prog = new ProgramTest(ref Execute);
        prog.AddMethod();
        prog.execute();
    }
}

或 您需要将Print方法分配给主要方法执行委托,如下所示

class Program
{
    static void Main(string[] args)
    {
        Action Execute = delegate { };            
        ProgramTest prog = new ProgramTest(ref Execute);

        Execute += prog.Print;

        prog.AddMethod();

        Execute();

    }
}

答案 3 :(得分:-1)

您的Program可能会公开一个事件,您的其他类可以向该事件注册另一个处理程序:

class Program
{
    public static event Action MyEvent;
    static void Main(string[] args)
    {
        ProgramTest prog = new ProgramTest();

        prog.AddMethod();

        // raise the event and invoke the registered handlers
        MyEvent?.Invoke();
    }
}

class ProgramTest
{
    private Action handler;

    public ProgramTest()
    {
        handler = Print;
    }

    public void AddMethod()
    {
        Program.MyEvent += handler;  // regsiter the execute-delegate to the event
        // or directly: Program.MyEvent += Print;
    }

    public void Print()
    {
        Console.WriteLine("test");
        Console.ReadLine();
    }
}