从函数返回事件的语法是什么? (不要调用事件,返回它以便它可以绑定到函数)。
我有一个容器类,其中包含一个字典,其中每个成员都有一个事件。
目的是能够写出这样的东西:
Container c = new Container();
c.CreateEventForKey("a"); // Create the member in the dictionary
c.EventForKey("a") += some_function; // Bind some_function to the event in the "a" member
c.OnEventForKey("a","b"); // Calls some_function with argument "b"
Container类看起来像这样:
public class Container {
public class Member {
public event Action<string> AnEvent;
public void OnEvent( string v ) { if(AnEvent!=null) { AnEvent(v); } }
}
protected Dictionary<string,Member> members;
// This seems to work OK.
public void OnEventForKey(string k, string v) {
if ( members.ContainsKey(k) ) { members[k].OnEvent(v); }
else { /* report error */ }
}
// Can't get this to compile.
public event Action<string> EventForKey(string k ) {
if ( members.ContainsKey(k) ) { return members[k].AnEvent; }
else { /* report error */ }
}
}
如何定义EventForKey
以便这样做符合我的期望?
答案 0 :(得分:8)
从函数返回事件的语法是什么?
你不能,轻松。事件 - 就像属性 - 并不是真正的第一类“对象”;他们是一个班级的成员。你并不是真的拥有一个班级成员 - 你试图将代表留在字典中。
你可以创建自己的“类似事件”的容器,但考虑其他设计可能更好,例如
c.Subscribe("a", SomeFunction);
c.OnEventForKey("a");
您可能希望看一下EventHandlerList
的灵感。
答案 1 :(得分:0)
为什么不简单地返回会员并订阅它的活动?
public IMember MemberForKey(string key) // return IMember
{
if (!members.ContainsKey(key))
throw new Exception();
return members[key];
}
然后订阅:
Container c = new Container();
c.CreateEventForKey("a");
c.MemberForKey("a").AnEvent += some_function;
c.OnEventForKey("a", "b");
但您在OnEvent
课程中有公共Member
方法。为了禁止客户端引发事件,您可以创建仅显示事件的界面。只需通过Member
类实现此接口:
public interface IMember
{
event Action<string> AnEvent;
}
是的,你不能返回事件,因为实际上事件不是对象,它是两个方法add
和remove
的集合,它们将委托添加到委托类型的内部字段中。以下是您的活动的样子:
private Action<string> _action; // field of delegate type
public event Action<string> AnEvent
{
add { _action += value; }
remove { _action -= value; }
}
事件的目的是仅为客户端提供两个操作 - 添加和删除处理程序。委托本身对客户隐藏。你可以把它公之于众:
public Action<string> _action;
但在这种情况下,任何客户都可以调用它。
更新:如果你想使用订阅/删除语法,那么只需使用带有处理程序的字典:
public class Container
{
private Dictionary<string, Action<string>> handlers =
new Dictionary<string, Action<string>>();
public void CreateEventForKey(string key)
{
// with empty handler added you can avoid null check
handlers.Add(key, (value) => { });
}
public void OnEventForKey(string key, string value)
{
if (!handlers.ContainsKey(key))
throw new Exception();
handlers[key](value);
}
public void Subscribe(string key, Action<string> handler)
{
if (!handlers.ContainsKey(key))
throw new Exception();
handlers[key] += handler;
}
}
答案 2 :(得分:0)
以下是完整的工作示例:
class Program
{
static void Main(string[] args)
{
Container c = new Container();
c.CreateEventForKey("a"); // Create the member in the dictionary
c.EventForKey("a").Add(str => Console.WriteLine(str));
c.EventForKey("a").Add(str => Console.WriteLine(str.ToUpper()));
c.OnEventForKey("a", "baa baa black sheep");
Console.ReadLine();
}
}
public class Container
{
public class Member
{
public List<Action<string>> AnEvent = new List<Action<string>>();
public void OnEvent(string v)
{
if (AnEvent != null)
{
this.AnEvent.ForEach(action => action(v));
}
}
public void AddEvent(Action<string> action)
{
this.AnEvent.Add(action);
}
}
protected Dictionary<string, Member> members = new Dictionary<string,Member>();
public void CreateEventForKey(string key)
{
this.members[key] = new Member();
}
// This seems to work OK.
public void OnEventForKey(string k, string v)
{
if (members.ContainsKey(k)) { members[k].OnEvent(v); }
else { /* report error */ }
}
public List<Action<string>> EventForKey(string k)
{
if (members.ContainsKey(k)) { return members[k].AnEvent; }
else { throw new KeyNotFoundException(); }
}
}
区别在于通过使用委托列表来表现与事件类似的行为。