@@ -21,21 +21,28 @@ namespace GitHub.VisualStudio.Base
21
21
public class TeamExplorerServiceHolder : ITeamExplorerServiceHolder
22
22
{
23
23
static readonly ILogger log = LogManager . ForContext < TeamExplorerServiceHolder > ( ) ;
24
- readonly IVSUIContextFactory uiContextFactory ;
25
24
readonly Dictionary < object , Action < ILocalRepositoryModel > > activeRepoHandlers = new Dictionary < object , Action < ILocalRepositoryModel > > ( ) ;
26
25
ILocalRepositoryModel activeRepo ;
27
26
bool activeRepoNotified = false ;
28
27
29
28
IServiceProvider serviceProvider ;
30
29
IVSGitExt gitService ;
31
30
IVSUIContext gitUIContext ;
31
+ IVSUIContextFactory uiContextFactory ;
32
32
33
33
// ActiveRepositories PropertyChanged event comes in on a non-main thread
34
34
readonly SynchronizationContext syncContext ;
35
35
36
- public TeamExplorerServiceHolder ( IVSUIContextFactory uiContextFactory , IVSGitExt gitService )
36
+ /// <summary>
37
+ /// This class relies on IVSUIContextFactory to get the UIContext object that provides information
38
+ /// when VS switches repositories. Unfortunately, for some reason MEF fails to create the instance
39
+ /// when imported from the constructor, so it's imported manually when first accessed via the
40
+ /// ServiceProvider instance (when mocking, make sure that the ServiceProvider includes this factory)
41
+ /// </summary>
42
+ /// <param name="gitService"></param>
43
+ [ ImportingConstructor ]
44
+ public TeamExplorerServiceHolder ( IVSGitExt gitService )
37
45
{
38
- this . uiContextFactory = uiContextFactory ;
39
46
this . GitService = gitService ;
40
47
syncContext = SynchronizationContext . Current ;
41
48
}
@@ -52,7 +59,7 @@ public IServiceProvider ServiceProvider
52
59
serviceProvider = value ;
53
60
if ( serviceProvider == null )
54
61
return ;
55
- GitUIContext = GitUIContext ?? uiContextFactory . GetUIContext ( new Guid ( Guids . GitSccProviderId ) ) ;
62
+ GitUIContext = GitUIContext ?? UIContextFactory . GetUIContext ( new Guid ( Guids . GitSccProviderId ) ) ;
56
63
UIContextChanged ( GitUIContext ? . IsActive ?? false , false ) ;
57
64
}
58
65
}
@@ -80,7 +87,7 @@ public void Subscribe(object who, Action<ILocalRepositoryModel> handler)
80
87
81
88
bool notificationsExist ;
82
89
ILocalRepositoryModel repo ;
83
- lock ( activeRepoHandlers )
90
+ lock ( activeRepoHandlers )
84
91
{
85
92
repo = ActiveRepo ;
86
93
notificationsExist = activeRepoNotified ;
@@ -128,7 +135,7 @@ public void ClearServiceProvider(IServiceProvider provider)
128
135
129
136
public void Refresh ( )
130
137
{
131
- GitUIContext = GitUIContext ?? uiContextFactory . GetUIContext ( new Guid ( Guids . GitSccProviderId ) ) ;
138
+ GitUIContext = GitUIContext ?? UIContextFactory . GetUIContext ( new Guid ( Guids . GitSccProviderId ) ) ;
132
139
UIContextChanged ( GitUIContext ? . IsActive ?? false , true ) ;
133
140
}
134
141
@@ -142,14 +149,19 @@ void NotifyActiveRepo()
142
149
}
143
150
}
144
151
145
- void UIContextChanged ( object sender , UIContextChangedEventArgs e )
152
+ void UIContextChanged ( object sender , IVSUIContextChangedEventArgs e )
146
153
{
147
154
Guard . ArgumentNotNull ( e , nameof ( e ) ) ;
148
155
149
156
ActiveRepo = null ;
150
157
UIContextChanged ( e . Activated , false ) ;
151
158
}
152
159
160
+ /// <summary>
161
+ /// This is called on a background thread. Do not do synchronous GetService calls here.
162
+ /// </summary>
163
+ /// <param name="active"></param>
164
+ /// <param name="refresh"></param>
153
165
async void UIContextChanged ( bool active , bool refresh )
154
166
{
155
167
Debug . Assert ( ServiceProvider != null , "UIContextChanged called before service provider is set" ) ;
@@ -170,7 +182,7 @@ async void UIContextChanged(bool active, bool refresh)
170
182
{
171
183
log . Error ( "Error 2001: ActiveRepositories is null. GitService: '{GitService}'" , GitService ) ;
172
184
GitService . Refresh ( ServiceProvider ) ;
173
- repos = GitService ? . ActiveRepositories ;
185
+ repos = GitService . ActiveRepositories ;
174
186
if ( repos == null )
175
187
log . Error ( "Error 2002: ActiveRepositories is null. GitService: '{GitService}'" , GitService ) ;
176
188
}
@@ -245,6 +257,74 @@ IVSGitExt GitService
245
257
gitService . ActiveRepositoriesChanged += UpdateActiveRepo ;
246
258
}
247
259
}
260
+
261
+ IVSUIContextFactory UIContextFactory
262
+ {
263
+ get
264
+ {
265
+ if ( uiContextFactory == null )
266
+ {
267
+ uiContextFactory = ServiceProvider . GetServiceSafe < IVSUIContextFactory > ( ) ;
268
+ }
269
+ return uiContextFactory ;
270
+ }
271
+ }
272
+ }
273
+
274
+ [ Export ( typeof ( IVSUIContextFactory ) ) ]
275
+ [ PartCreationPolicy ( CreationPolicy . Shared ) ]
276
+ class VSUIContextFactory : IVSUIContextFactory
277
+ {
278
+ public IVSUIContext GetUIContext ( Guid contextGuid )
279
+ {
280
+ return new VSUIContext ( UIContext . FromUIContextGuid ( contextGuid ) ) ;
281
+ }
282
+ }
283
+
284
+ class VSUIContextChangedEventArgs : IVSUIContextChangedEventArgs
285
+ {
286
+ public bool Activated { get ; }
287
+
288
+ public VSUIContextChangedEventArgs ( bool activated )
289
+ {
290
+ Activated = activated ;
291
+ }
292
+ }
293
+
294
+ class VSUIContext : IVSUIContext
295
+ {
296
+ readonly UIContext context ;
297
+ readonly Dictionary < EventHandler < IVSUIContextChangedEventArgs > , EventHandler < UIContextChangedEventArgs > > handlers =
298
+ new Dictionary < EventHandler < IVSUIContextChangedEventArgs > , EventHandler < UIContextChangedEventArgs > > ( ) ;
299
+ public VSUIContext ( UIContext context )
300
+ {
301
+ this . context = context ;
302
+ }
303
+
304
+ public bool IsActive { get { return context . IsActive ; } }
305
+
306
+ public event EventHandler < IVSUIContextChangedEventArgs > UIContextChanged
307
+ {
308
+ add
309
+ {
310
+ EventHandler < UIContextChangedEventArgs > handler = null ;
311
+ if ( ! handlers . TryGetValue ( value , out handler ) )
312
+ {
313
+ handler = ( s , e ) => value . Invoke ( s , new VSUIContextChangedEventArgs ( e . Activated ) ) ;
314
+ handlers . Add ( value , handler ) ;
315
+ }
316
+ context . UIContextChanged += handler ;
317
+ }
318
+ remove
319
+ {
320
+ EventHandler < UIContextChangedEventArgs > handler = null ;
321
+ if ( handlers . TryGetValue ( value , out handler ) )
322
+ {
323
+ handlers . Remove ( value ) ;
324
+ context . UIContextChanged -= handler ;
325
+ }
326
+ }
327
+ }
248
328
}
249
329
250
330
static class IGitRepositoryInfoExtensions
0 commit comments