@@ -64,23 +64,36 @@ public static IListState<T> Empty<TOwner>(TOwner owner, [CallerMemberName] strin
6464 /// <typeparam name="TOwner">Type of the owner of the state.</typeparam>
6565 /// <param name="owner">The owner of the state.</param>
6666 /// <param name="valueProvider">The provider of the initial value of the state.</param>
67+ /// <param name="name">The caller member name, used as a stable cache key.</param>
68+ /// <param name="line">The caller line number, used as a stable cache key.</param>
6769 /// <returns>A feed that encapsulate the source.</returns>
68- public static IListState < T > Value < TOwner > ( TOwner owner , Func < IImmutableList < T > > valueProvider )
70+ public static IListState < T > Value < TOwner > ( TOwner owner , Func < IImmutableList < T > > valueProvider , [ CallerMemberName ] string ? name = null , [ CallerLineNumber ] int line = - 1 )
6971 where TOwner : class
70- // Note: We force the usage of delegate so 2 properties which are doing State.Value(this, () => 42) will effectively have 2 distinct states.
71- => AttachedProperty . GetOrCreate ( owner , valueProvider , static ( o , v ) => SourceContext . GetOrCreate ( o ) . CreateListState ( Option < IImmutableList < T > > . Some ( v ( ) ) ) ) ;
72+ // Use CallerMemberName+line as stable cache key instead of delegate reference identity.
73+ // Delegate instances can be recreated after MetadataUpdater.ApplyUpdate on WASM,
74+ // which would cause cache misses and state recreation (spec 033).
75+ => AttachedProperty . GetOrCreate < TOwner , ( string , int ) , Func < IImmutableList < T > > , IListState < T > > (
76+ owner ,
77+ ( name ?? throw new InvalidOperationException ( "The name of the list state must not be null" ) , line < 0 ? throw new InvalidOperationException ( "The provided line number is invalid." ) : line ) ,
78+ valueProvider ,
79+ static ( o , _ , v ) => SourceContext . GetOrCreate ( o ) . CreateListState ( Option < IImmutableList < T > > . Some ( v ( ) ) ) ) ;
7280
7381 /// <summary>
7482 /// Gets or creates a list state from a static initial list of items.
7583 /// </summary>
7684 /// <typeparam name="TOwner">Type of the owner of the state.</typeparam>
7785 /// <param name="owner">The owner of the state.</param>
7886 /// <param name="valueProvider">The provider of the initial value of the state.</param>
87+ /// <param name="name">The caller member name, used as a stable cache key.</param>
88+ /// <param name="line">The caller line number, used as a stable cache key.</param>
7989 /// <returns>A feed that encapsulate the source.</returns>
80- public static IListState < T > Value < TOwner > ( TOwner owner , Func < ImmutableList < T > > valueProvider )
90+ public static IListState < T > Value < TOwner > ( TOwner owner , Func < ImmutableList < T > > valueProvider , [ CallerMemberName ] string ? name = null , [ CallerLineNumber ] int line = - 1 )
8191 where TOwner : class
82- // Note: We force the usage of delegate so 2 properties which are doing State.Value(this, () => 42) will effectively have 2 distinct states.
83- => AttachedProperty . GetOrCreate ( owner , valueProvider , static ( o , v ) => SourceContext . GetOrCreate ( o ) . CreateListState ( Option < IImmutableList < T > > . Some ( v ( ) ) ) ) ;
92+ => AttachedProperty . GetOrCreate < TOwner , ( string , int ) , Func < ImmutableList < T > > , IListState < T > > (
93+ owner ,
94+ ( name ?? throw new InvalidOperationException ( "The name of the list state must not be null" ) , line < 0 ? throw new InvalidOperationException ( "The provided line number is invalid." ) : line ) ,
95+ valueProvider ,
96+ static ( o , _ , v ) => SourceContext . GetOrCreate ( o ) . CreateListState ( Option < IImmutableList < T > > . Some ( v ( ) ) ) ) ;
8497
8598 /// <summary>
8699 /// Gets or creates a list state from a static initial list of items.
0 commit comments