首先,Unity支持.NET 3.5的一个子集,其中特定的子集取决于您的构建参数。
转到您的问题,C#中的一般事件模式是使用委托和事件关键字。由于您只希望处理程序在传入的水果与其方法定义兼容时才被调用,因此可以使用字典来完成查找。技巧是将代表存储为什么类型。你可以用一点神奇的类型,使工作和所有都
Dictionary<Type, Action<Fruit>> handlers = new Dictionary<Type, Action<Fruit>>();
这是不理想的,因为现在所有的处理程序似乎接受Fruit
,而不是更具体的类型。然而,这只是内部表示,公众人员仍然会通过添加特定处理程序
public void RegisterHandler<T>(Action<T> handler) where T : Fruit
这会保持公共API的清洁和类型特定。代表在内部需要将Action<T>
更改为Action<Fruit>
。为此,创建一个新的代理,它接受Fruit
并将其转换为T
。
Action<Fruit> wrapper = fruit => handler(fruit as T);
这当然不是安全的演员。如果它传递的不是T
(或从T
继承),它会崩溃。这就是为什么它非常重要,它只存储在内部而不暴露在课堂之外。将该函数存储在处理程序字典中的Type
密钥typeof(T)
下。
在调用事件之前需要一个自定义函数。这个函数需要调用所有事件处理程序,从继承链上的参数类型到最通用的Fruit
处理程序。这允许函数在任何子类型参数上触发,而不仅仅是它的特定类型。这对我来说似乎是直觉行为,但如果需要可以省略。
最后,可以暴露正常事件以允许以通常方式添加捕获所有处理程序Fruit
。
下面是完整的例子。请注意,该示例非常简单,并排除了一些典型的安全检查,如空检查。如果没有从child
到parent
的继承链,那么也存在潜在的无限循环。应视实际情况扩大实际执行情况。它也可以使用一些优化。特别是在高使用情况下,缓存继承链可能很重要。
public class Fruit { }
class FruitHandlers
{
private Dictionary<Type, Action<Fruit>> handlers = new Dictionary<Type, Action<Fruit>>();
public event Action<Fruit> FruitAdded
{
add
{
handlers[typeof(Fruit)] += value;
}
remove
{
handlers[typeof(Fruit)] -= value;
}
}
public FruitHandlers()
{
handlers = new Dictionary<Type, Action<Fruit>>();
handlers.Add(typeof(Fruit), null);
}
static IEnumerable<Type> GetInheritanceChain(Type child, Type parent)
{
for (Type type = child; type != parent; type = type.BaseType)
{
yield return type;
}
yield return parent;
}
public void RegisterHandler<T>(Action<T> handler) where T : Fruit
{
Type type = typeof(T);
Action<Fruit> wrapper = fruit => handler(fruit as T);
if (handlers.ContainsKey(type))
{
handlers[type] += wrapper;
}
else
{
handlers.Add(type, wrapper);
}
}
private void InvokeFruitAdded(Fruit fruit)
{
foreach (var type in GetInheritanceChain(fruit.GetType(), typeof(Fruit)))
{
if (handlers.ContainsKey(type) && handlers[type] != null)
{
handlers[type].Invoke(fruit);
}
}
}
}
你可以做水果一般 - '水果' –
@ DanielA.White我不知道我怎么看这将解决这个问题。你能详细说明一下吗? – thomas88wp
我编辑了你的标题。请参阅:“[应该在其标题中包含”标签“](http://meta.stackexchange.com/questions/19190/)”,其中的共识是“不,他们不应该”。 –