88using System . Linq ;
99using Azure . Provisioning . Expressions ;
1010using Azure . Provisioning . Primitives ;
11+ using Azure . Provisioning . Utilities ;
1112
1213namespace Azure . Provisioning ;
1314
@@ -58,7 +59,15 @@ internal override void Assign(IBicepValue source)
5859 {
5960 _values = typed . _values ;
6061 }
62+
63+ // Everything else is handled by the base Assign
6164 base . Assign ( source ) ;
65+
66+ // handle self in all the items
67+ foreach ( var kv in _values )
68+ {
69+ SetSelfForItem ( kv . Value , kv . Key ) ;
70+ }
6271 }
6372
6473 /// <summary>
@@ -68,23 +77,78 @@ internal override void Assign(IBicepValue source)
6877 public static implicit operator BicepDictionary < T > ( ProvisioningVariable reference ) =>
6978 new ( new BicepValueReference ( reference , "{}" ) , BicepSyntax . Var ( reference . BicepIdentifier ) ) { _isSecure = reference is ProvisioningParameter p && p . IsSecure } ;
7079
80+ private BicepValueReference ? GetItemSelf ( string key ) =>
81+ _self is not null
82+ ? new BicepDictionaryValueReference ( _self . Construct , _self . PropertyName , _self . BicepPath ? . ToArray ( ) , key )
83+ : null ;
84+
85+ private void SetSelfForItem ( BicepValue < T > item , string key )
86+ {
87+ var itemSelf = GetItemSelf ( key ) ;
88+ item . SetSelf ( itemSelf ) ;
89+ }
90+
91+ private void RemoveSelfForItem ( BicepValue < T > item )
92+ {
93+ item . SetSelf ( null ) ;
94+ }
95+
7196 /// <summary>
7297 /// Gets or sets a value in a BicepDictionary.
7398 /// </summary>
7499 /// <param name="key">Key of the value.</param>
75100 /// <returns>The value.</returns>
76101 public BicepValue < T > this [ string key ]
77102 {
78- get => _values [ key ] ;
79- set => _values [ key ] = value ;
103+ get
104+ {
105+ if ( _values . TryGetValue ( key , out var value ) )
106+ {
107+ return value ;
108+ }
109+ // the key does not exist, we put a value factory as the literal value of this bicep value
110+ // this would blow up when we try to compile it later, but it would be fine if we convert it to an expression
111+ return new BicepValue < T > ( GetItemSelf ( key ) , ( ) => _values [ key ] . Value ) ;
112+ }
113+
114+ set
115+ {
116+ _values [ key ] = value ;
117+ // update the _self pointing the new item
118+ SetSelfForItem ( value , key ) ;
119+ }
120+ }
121+
122+ public void Add ( string key , BicepValue < T > value )
123+ {
124+ _values . Add ( key , value ) ;
125+ // update the _self pointing the new item
126+ SetSelfForItem ( value , key ) ;
127+ }
128+
129+ public void Add ( KeyValuePair < string , BicepValue < T > > item )
130+ {
131+ _values . Add ( item . Key , item . Value ) ;
132+ // update the _self pointing the new item
133+ SetSelfForItem ( item . Value , item . Key ) ;
80134 }
81135
82- public void Add ( string key , BicepValue < T > value ) => _values . Add ( key , value ) ;
83- public void Add ( KeyValuePair < string , BicepValue < T > > item ) => _values . Add ( item . Key , item . Value ) ;
136+ public bool Remove ( string key )
137+ {
138+ var removedItem = _values [ key ] ;
139+ // maintain the self reference for the removed item
140+ RemoveSelfForItem ( removedItem ) ;
141+ return _values . Remove ( key ) ;
142+ }
84143
85- // TODO: Decide whether it's important to "unlink" resources on removal
86- public bool Remove ( string key ) => _values . Remove ( key ) ;
87- public void Clear ( ) => _values . Clear ( ) ;
144+ public void Clear ( )
145+ {
146+ foreach ( var kv in _values )
147+ {
148+ RemoveSelfForItem ( kv . Value ) ;
149+ }
150+ _values . Clear ( ) ;
151+ }
88152
89153 public ICollection < string > Keys => _values . Keys ;
90154 public ICollection < BicepValue < T > > Values => _values . Values ;
0 commit comments