我有一个使用PRISM事件聚合器模式定义的简单事件
public class TestEvent : PubSubEvent
{
}
public static class PrismEvents
{
public static readonly IEventAggregator EventAggregator = new EventAggregator();
public static readonly TestEvent EventTest = EventAggregator.GetEvent<TestEvent>();
}
我有一个订户类,该事件使用lambda进行订阅。请注意,在订阅代码中使用局部变量(i)
public class SubScriber
{
public SubScriber()
{
int i = 5;
PrismEvents.EventTest.Subscribe(() =>
{
Console.WriteLine("Event Fired");//not getting called
i = 10; //commenting this line will execute the subscription code
});
}
}
在发布者侧创建订户,然后调用GC,然后发布事件。
订阅代码未执行!
class Program
{
static void Main(string[] args)
{
new SubScriber();
GC.Collect(); //commenting this line will execute the subscription code
PrismEvents.EventTest.Publish();
Console.ReadKey();
}
}
点对
注释局部变量(i = 10)的使用将修复 问题。订阅代码将按预期执行
评论GC.collect将解决此问题。订阅代码将 按预期执行
此行为的原因是什么?
答案 0 :(得分:0)
好问题。 我没有所有答案,但是Prism使用WeakReference。 订阅可在参数中使用的委托(动作)上创建WeakReference。 确切地说,WeakReference是在委托的Target上进行的。 这里有一些代码可以更好地理解发生了什么:
public class SubScriber
{
[CompilerGenerated]
private sealed class <>c__DisplayClass0_0
{
public int i;
internal void ctor>b__0()
{
Console.WriteLine("Event Fired action1");
this.i = 11;
}
}
[CompilerGenerated]
[Serializable]
private sealed class <>c
{
public static readonly Program.SubScriber.<>c <>9 = new Program.SubScriber.<>c();
public static Action <>9__0_1;
internal void ctor>b__0_1()
{
Console.WriteLine("Event Fired action2");
}
}
public SubScriber()
{
Program.SubScriber.<>c__DisplayClass0_0 <>c__DisplayClass0_ = new Program.SubScriber.<>c__DisplayClass0_0();
<>c__DisplayClass0_.i = 5;
Action action = new Action(<>c__DisplayClass0_.<.ctor>b__0);
Action arg_41_0;
if ((arg_41_0 = Program.SubScriber.<>c.<>9__0_1) == null)
{
arg_41_0 = (Program.SubScriber.<>c.<>9__0_1 = new Action(Program.SubScriber.<>c.<>9.<.ctor>b__0_1));
}
Action action2 = arg_41_0;
string arg_59_0 = "Target 1 = ";
object expr_4D = action.Target;
Console.WriteLine(arg_59_0 + ((expr_4D != null) ? expr_4D.ToString() : null));
string arg_7B_0 = "Target 2 = ";
object expr_6F = action2.Target;
Console.WriteLine(arg_7B_0 + ((expr_6F != null) ? expr_6F.ToString() : null));
Program.PrismEvents.EventTest.Subscribe(action);
Program.PrismEvents.EventTest.Subscribe(action2);
}
~SubScriber()
{
Console.WriteLine("SubScriber destructed");
}
}
我们看到“ SubScriber destructed”显示在“ Publish”之前。 有趣的是,还可以使用ILSpy查看生成的内容:
class ListPage extends StatelessWidget {
const ListPage({Key key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('List Example'),
),
body: ListView.separated(
itemBuilder: (context, index) {
return ListItem();
},
itemCount: 3,
separatorBuilder: (_, int index) => Divider(),
),
);
}
}
class ListItem extends StatefulWidget {
ListItem({Key key}) : super(key: key);
@override
_ListItemState createState() => _ListItemState();
}
class _ListItemState extends State<ListItem> {
bool _expanded;
@override
void initState() {
_expanded = false;
super.initState();
}
@override
Widget build(BuildContext context) {
return InkWell(
onTap: () {
setState(() {
_expanded = !_expanded;
});
},
child: Text(
'Line1\nLine2\nLine3',
maxLines: _expanded ? null : 1,
softWrap: true,
style: const TextStyle(fontSize: 22),
),
);
}
}
我看到的区别是第二个操作具有一个静态只读字段,该字段在委托中包含一个实例...
关于, Sybaris