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

问题描述 投票:1回答:4

我正在寻找一种方法来允许另一个类通过调用该类中的方法向我的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()时,没有任何反应。

我怎样才能使它工作?

c# delegates action
4个回答
1
投票

另一个选择是将(immutable)委托放在一个可变容器中。

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();
    }
}

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();
        }
    }
}

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方法分配给main方法执行委托,如下所示

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

        Execute += prog.Print;

        prog.AddMethod();

        Execute();

    }
}

-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();
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.