我正在开发一个系统,其中Watcher
可以设置为对Event
感兴趣,如果Action
Event
,则调用Action
传递正确的类型。
现在Event
在调用时需要有关Action
的信息。
在下面的代码中,我使用委托作为Watcher
属性(不是.NET方式的属性,只是字段/成员/等等......)在设置{时传递Event函数{1}}。
当然,代码的问题在于 // Step3 ,当我这样做时,字段TheEvent
为空。只有Watcher
通过Event
后才会知道。
如何告知Watcher
Action
在Event
被分配之前Event
获取namespace ConsoleApplication1
{
using System;
internal class Program
{
static void Main(string[] args)
{
//Step1: choose the IEvent: NumericEvent
//Step2: create Watcher<NumbericEvent>
Watcher<NumericEvent> aWatcher = new Watcher<NumericEvent>();
//Step3: Choose and add an action
aWatcher.TheAction = new AlphaAction();
//Step3 bind the ActionProperties
aWatcher.TheAction.AnActionPropertyA = aWatcher.TheEvent.GetProperty1;
aWatcher.TheAction.AnActionPropertyB = aWatcher.TheEvent.GetProperty2;
//Step4 Bind the event
NumericEvent anEvent = new NumericEvent();
aWatcher.Call(anEvent);
}
}
internal class AlphaAction
{
internal delegate string ActionPropertyA();
internal delegate int ActionPropertyB();
internal ActionPropertyA AnActionPropertyA;
internal ActionPropertyB AnActionPropertyB;
internal string ActionPropertyC;
public void Run()
{
Console.Write(AnActionPropertyA.Invoke());
Console.Write(AnActionPropertyB.Invoke());
}
}
internal interface IEvent
{
}
internal class NumericEvent:IEvent
{
internal string EventProperty1 = "Property1";
internal int EventProperty2 = 2;
internal string GetProperty1()
{
return EventProperty1;
}
internal int GetProperty2()
{
return EventProperty2;
}
}
internal class Watcher<T> where T:IEvent
{
internal NumericEvent TheEvent;
internal AlphaAction TheAction;
internal void Call(IEvent anEvent)
{
TheEvent = (NumericEvent)anEvent;
TheAction.Run();
}
}
}
所需的属性?
internal class Program
{
static void Main(string[] args)
{
//Step1: choose the IEvent: NumericEvent
//Step2: create Watcher<NumbericEvent>
Watcher<NumericEvent> aWatcher = new Watcher<NumericEvent>();
//Step3: Choose and add an action
aWatcher.TheAction = new AlphaAction();
//Step3 bind the ActionProperties
MethodInfo method1 = typeof(NumericEvent).GetMethod("GetProperty1");
aWatcher.TheAction.AnActionPropertyA = (AlphaAction.ActionPropertyA)Delegate.CreateDelegate(typeof(AlphaAction.ActionPropertyA), aWatcher.TheEvent, method1);
MethodInfo method2 = typeof(NumericEvent).GetMethod("GetProperty2");
aWatcher.TheAction.AnActionPropertyB = (AlphaAction.ActionPropertyB)Delegate.CreateDelegate(typeof(AlphaAction.ActionPropertyB), aWatcher.TheEvent, method2);
//Step4 an event is created and passed to the Watcher
NumericEvent anEvent = new NumericEvent("bla",3);
if (aWatcher.GType() == anEvent.GetType())
aWatcher.Call(anEvent);
}
}
internal abstract class BaseAction
{
public abstract void Run();
}
internal class AlphaAction: BaseAction
{
internal delegate string ActionPropertyA();
internal delegate int ActionPropertyB();
internal ActionPropertyA AnActionPropertyA;
internal ActionPropertyB AnActionPropertyB;
internal string ActionPropertyC;
public override void Run()
{
Console.Write(AnActionPropertyA.Invoke());
Console.Write(AnActionPropertyB.Invoke());
}
}
internal interface IEvent
{
}
internal class NumericEvent : IEvent
{
private readonly string _eventProperty1;
private readonly int _eventProperty2;
public NumericEvent(string p1, int p2)
{
_eventProperty1 = p1;
_eventProperty2 = p2;
}
public string GetProperty1()
{
return _eventProperty1;
}
public int GetProperty2()
{
return _eventProperty2;
}
}
internal class Watcher<T> where T:IEvent
{
internal T TheEvent;
internal AlphaAction TheAction;
internal Type GType()
{
return typeof(T);
}
internal void Call(IEvent anEvent)
{
TheEvent = (T)anEvent;
TheAction.Run();
}
}
可能需要采取完全不同的方法,但我希望这可以解决问题和期望的结果。
更新
我使用Delegate.CreateDelegate(https://msdn.microsoft.com/en-us/library/s3860fy3.aspx)做了一些操作,但它仍然不太正确,因为如果分配时为null,则将其视为静态:
命名空间ConsoleApplication1 { 使用系统; 使用System.Reflection;
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/unistd.h>
#include "sched.h"
#include "sched1.h"
/* This function is called when the module t is loaded. */
int process_init(void)
{
printk(KERN_INFO "lOADING MODULE \n");
printk(KERN_INFO "PID \t PPID \t PNAME \t SIZE \n");
struct task_struct *task;
for_each_process(task)
{
printk(KERN_INFO "%d \t %d\t %s \t %d \n", task->pid,task->ppid,task->comm,task->sz);
}
return 0;
}
}
答案 0 :(得分:1)
如果我理解你的需要,那么你可以使用Galasoft's MVVM Light Toolkit。
重点如下:
SomeMessage
SomeMessage
。我们举一个例子:
// First you create the message with the needed properties.
public SomeMessage
{
public string Content { get; set; }
}
// Then at some places you register for listening to this type of message
Messenger.Default.Register<SomeMessage>(
this,
message => YourMethodThatProcessesTheMessage(message)
);
// Your method knows the exact type of the message
// So you can access all the properties of the message
private void YourMethodThatProcessesTheMessage(SomeMessage message)
{
Console.WriteLine(message.Content);
}
// At another place you can simply send a message to all the listeners
var message = new SomeMessage() { Content = "something" };
Messenger.Default.Send<SomeMessage>(message);
答案 1 :(得分:1)
如果我理解你正确,你想要做以下事情:有一个Watcher
类来查找特定事件,当它被传递给类时,应该触发一个动作,并且该事件应该作为参数。
我不完全理解为什么你需要这个洞的东西以及为什么你按照你的方式设置东西但这里有一个简单的实现可能会有所帮助:
internal interface IEvent { }
internal class Watcher<T> where T : IEvent
{
internal Action<T> Action;
public void On(IEvent evnt)
{
if (evnt is T) Action?.Invoke((T) evnt);
}
}
您可以通过实施IEvent
来创建新事件,并且可以注册当观察者通过设置Action
字段注册指定类型的操作时应触发的操作。 e.g。
var watcher = new Watcher<NumberEvent>();
watcher.Action += e => Console.WriteLine($"Got a number: {e.Number}");
watcher.On(new StringEvent { Text = "hello"});
watcher.On(new NumberEvent { Number = 1337});
何时定义
internal class NumberEvent : IEvent
{
internal int Number;
}
internal class StringEvent : IEvent
{
internal string Text;
}
如果我没有正确理解你的问题(并且很有可能我没有),请解释你的程序应该做什么。
以下是您实施的一些想法/问题:
Watcher<T>
),但T
未在观察者内部使用。您可能希望将NumericEvent
替换为T
,并检查指定的IEvent
是否属于T
类型(或您的NumericEvent
)。您的编码使IEvent
过时了。string EventProperty { get; }
。您不必制作GetProperty1()
方法(您的字段也是内部的,为什么要使用该方法?)答案 2 :(得分:1)
您的代码存在的问题是aWatcher.TheEvent
行中的aWatcher.TheAction.AnActionPropertyA = aWatcher.TheEvent.GetProperty1;
(以及更新后的代码aWatcher.TheAction.AnActionPropertyA = (AlphaAction.ActionPropertyA)Delegate.CreateDelegate(typeof(AlphaAction.ActionPropertyA), aWatcher.TheEvent, method1);
)。
由于创建代理时aWatcher.TheEvent
为null
,因此代理始终使用null
。您不关心以后在行TheEvent = (NumericEvent)anEvent;
中分配事件。
要实现这一点,您需要让代表知道将来会有一个课程。这就是我将如何做到的,但我怀疑这会破坏你想要它如何工作的逻辑。
void Main()
{
Watcher<NumericEvent> aWatcher = new Watcher<NumericEvent>();
aWatcher.TheAction = new AlphaAction<NumericEvent>();
aWatcher.TheAction.AnActionPropertyA = ne => ne.GetProperty1();
aWatcher.TheAction.AnActionPropertyB = ne => ne.GetProperty2();
NumericEvent anEvent = new NumericEvent("bla", 3);
if (aWatcher.GType() == anEvent.GetType())
aWatcher.Call(anEvent);
}
internal abstract class BaseAction<T> where T : IEvent
{
public abstract void Run(T theEvent);
}
internal class AlphaAction<T> : BaseAction<T> where T : IEvent
{
internal delegate string ActionPropertyA(T theEvent);
internal delegate int ActionPropertyB(T theEvent);
internal ActionPropertyA AnActionPropertyA;
internal ActionPropertyB AnActionPropertyB;
public override void Run(T theEvent)
{
Console.Write(AnActionPropertyA(theEvent));
Console.Write(AnActionPropertyB(theEvent));
}
}
internal interface IEvent
{
}
internal class NumericEvent : IEvent
{
private readonly string _eventProperty1;
private readonly int _eventProperty2;
public NumericEvent(string p1, int p2)
{
_eventProperty1 = p1;
_eventProperty2 = p2;
}
public string GetProperty1()
{
return _eventProperty1;
}
public int GetProperty2()
{
return _eventProperty2;
}
}
internal class Watcher<T> where T : IEvent
{
internal AlphaAction<T> TheAction;
internal Type GType()
{
return typeof(T);
}
internal void Call(T theEvent)
{
TheAction.Run(theEvent);
}
}