我正在寻找一种方法来允许另一个类通过调用该类中的方法向我的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()时,没有任何反应。
我怎样才能使它工作?
另一个选择是将(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();
}
}
你想要的是这个:
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();
}
}
}
您可以通过调用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();
}
}
你的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();
}
}