我有一个更理论化的问题,希望你能帮助我。
想象一下,你有以下课程:
public class Foo
{
public event EventHandler Invalid;
//some more Properties/Fields/Methods and stuff but only the event is important for my question
}
现在你还有两个类,一个初始化这个对象并使用另一个“监视”对象并执行其他操作的类:
public class Bar
{
private Foo _foo;
public void Main()
{
_foo = new Foo();
FooUtils.RegisterFoo(_foo);
//do some stuff with foo...
}
}
public static class FooUtils
{
public static void RegisterFoo(Foo foo)
{
foo.Invalid -= OnInvalid;
foo.Invalid += OnInvalid;
}
private static void OnInvalid(object sender, EventArgs args)
{
var foo = sender as Foo;
if (foo != null)
{
//do some stuff...
}
}
}
我想扩展FooUtils,在某些情况下它可以创建一个新的Foo实例,所以我认为“嘿没有问题只是将其作为参考传递。”,所以我将代码更改为以下... < / p>
public class Bar
{
private Foo _foo;
public void Main()
{
_foo = new Foo();
//do some stuff with foo...
FooUtils.RegisterFoo(ref _foo);
}
}
public static class FooUtils
{
public static void RegisterFoo(ref Foo foo)
{
foo.Invalid -= OnInvalid;
foo.Invalid += OnInvalid;
}
private static void OnInvalid(object sender, EventArgs args)
{
var foo = sender as Foo;
if (foo != null)
{
//do some stuff...
//create a new Instance and set it to ?!?
var helpMe = new Foo();
}
}
}
如果我在Register方法中实例化一个新的Foo,但是我需要在事件内部创建一个新实例(在var helpMe = new Foo();),
行,我将如何做到这一点,这个代码可以工作?那么最后这个字段bar内的_foo会更新吗?请记住,我可以在静态 FooUtils中注册几个Foos,并根据注册的Foo触发Invalid事件,相应的引用应该更新。这是否可能,如果没有什么是一个好的选择?
只是为了确保:是的,我知道我可以在Bar内部听取事件并将_foo字段设置在bar内部但是如果可能的话我想保持这种分离。
答案 0 :(得分:1)
您可以使用委托指向发件人通过引用传递的方法替换EventHandler
类中的Foo
:
public class Foo
{
public delegate void InvalidEventHandler(ref Foo sender, EventArgs args);
public event InvalidEventHandler Invalid;
}
然后您需要更改OnInvalid
方法:
private static void OnInvalid(ref Foo sender, EventArgs args)
{
if (sender != null)
{
//do some stuff...
sender = new Foo();
}
}
现在,在调用该方法时,您需要通过引用传递Foo
,并且Foo
类中的Boo
对象可以看到更改。
答案 1 :(得分:1)
public class Bar
{
private Foo _foo;
public void Main()
{
_foo = new Foo();
//do some stuff with foo...
FooUtils.RegisterFoo(_foo, ReferenceChanger);
}
public void ReferenceChanger (Foo anotherFoo)
{
_foo = anotherFoo;
}
}
public class Foo
{
public event EventHandler Invalid;
//some more Properties/Fields/Methods and stuff but only the event is important for my question
}
public static class FooUtils
{
private static Dictionary<Foo, Action<Foo>> actionsToCallDictionary;
public static void RegisterFoo( Foo foo, Action<Foo> changeReferenceAction)
{
foo.Invalid -= OnInvalid;
if (actionsToCallDictionary != null)
actionsToCallDictionary.Remove(foo);
foo.Invalid += OnInvalid;
if (actionsToCallDictionary == null)
actionsToCallDictionary = new Dictionary<Foo, Action<Foo>>();
actionsToCallDictionary[foo] = changeReferenceAction;
}
private static void OnInvalid(object sender, EventArgs args)
{
var foo = sender as Foo;
if (foo != null)
{
//do some stuff...
//create a new Instance and set it to ?!?
Action<Foo> referenceChanger;
if (actionsToCallDictionary != null && actionsToCallDictionary.TryGetValue(foo, out referenceChanger))
{
var changeWith = new Foo();
referenceChanger(changeWith);
}
}
}
}
但请注意,如果您不小心处理/管理该静态字典,可能会以内存泄漏结束。
另一个问题是在多线程环境中,您应该锁定/解锁该字典。