Dans la série des nouvelles qui ne font pas vraiment plaisir, il semblerait que SPDisposeCheck ne vérifie pas tout les patterns de Dispose présentés dans les liens suivants :
En effet, Stephen Vick montre que SPDisposeCheck ne vérifie pas les méthodes suivantes dans le fichier utilisé (basé sur le post de Roger Lamb) :
Ce qui fait quand même une petite tripoté de méthodes et d'objets qui ne sont pas vérifiés.
1: namespace SPDisposeTest
2: {
3: public class Class1
4: {
5: void CreatingSPSiteLeak()
6: {
7: SPSite siteCollection = new SPSite("http://moss");
8: // siteCollection leaked
9: }
10:
11: void CreatingSPSiteExplicitDisposeNoLeak()
12: {
13: SPSite siteCollection = null;
14: try
15: {
16: siteCollection = new SPSite("http://moss");
17: }
18: finally
19: {
20: if (siteCollection != null)
21: siteCollection.Dispose();
22: }
23: }
24:
25: void CreatingSPSiteWithAutomaticDisposeNoLeak()
26: {
27: using (SPSite siteCollection = new SPSite("http://moss"))
28: {
29: } // SPSite object siteCollection.Dispose() automatically called
30: }
31:
32: void OpenWebLeak()
33: {
34: using (SPWeb web = new SPSite(SPContext.Current.Web.Url).OpenWeb())
35: {
36: // SPSite leaked !
37: } // SPWeb object web.Dispose() automatically called
38: }
39:
40: void OpenWebNoLeak()
41: {
42: using (SPSite siteCollection = new SPSite("http://moss"))
43: {
44: using (SPWeb web = siteCollection.OpenWeb())
45: {
46: } // SPWeb object web.Dispose() automatically called
47: } // SPSite object siteCollection.Dispose() automatically called
48: }
49:
50: void AllWebsForEachLeak()
51: {
52: using (SPSite siteCollection = new SPSite("http://moss"))
53: {
54: using (SPWeb outerWeb = siteCollection.OpenWeb())
55: {
56: foreach (SPWeb innerWeb in siteCollection.AllWebs)
57: {
58: // explicit dispose here to avoid OOM’s with large # of webs
59: }
60: } // SPWeb object outerWeb.Dispose() automatically called
61: } // SPSite object siteCollection.Dispose() automatically called
62: }
63:
64: void AllWebsForEachNoLeakOrMemoryOOM()
65: {
66: using (SPSite siteCollection = new SPSite("http://moss"))
67: {
68: using (SPWeb outerWeb = siteCollection.OpenWeb())
69: {
70: foreach (SPWeb innerWeb in siteCollection.AllWebs)
71: {
72: try
73: {
74: // …
75: }
76: finally
77: {
78: if (innerWeb != null)
79: innerWeb.Dispose();
80: }
81: }
82: } // SPWeb object outerWeb.Dispose() automatically called
83: } // SPSite object siteCollection.Dispose() automatically called
84: }
85:
86: void AllWebsIndexerLeak()
87: {
88: using (SPSite siteCollection = new SPSite("http://moss"))
89: {
90: SPWeb web = siteCollection.AllWebs[0];
91: // SPWeb web leaked
92: } // SPSite object siteCollection.Dispose() automatically called
93: }
94:
95: void AllWebsIndexerNoLeak()
96: {
97: using (SPSite siteCollection = new SPSite("http://moss"))
98: {
99: using (SPWeb web = siteCollection.AllWebs[0])
100: {
101: } // SPWeb object web.Dispose() automatically called
102: } // SPSite object siteCollection.Dispose() automatically called
103: }
104:
105: void AllWebsAddLeak()
106: {
107: using (SPSite siteCollection = new SPSite("http://moss"))
108: {
109: SPWeb web = siteCollection.AllWebs.Add("site-relative URL");
110: // SPWeb web Leaked
111: } // SPSite object siteCollection.Dispose() automatically called
112: }
113:
114: void AllWebsAddNoLeak()
115: {
116: using (SPSite siteCollection = new SPSite("http://moss"))
117: {
118: using (SPWeb web = siteCollection.AllWebs.Add("site-relative URL"))
119: {
120: } // SPWeb object web.Dispose() automatically called
121: } // SPSite object siteCollection.Dispose() automatically called
122: }
123:
124: void SPLimitedWebPartManagerLeak()
125: {
126: using (SPSite siteCollection = new SPSite("http://moss"))
127: {
128: using (SPWeb web = siteCollection.OpenWeb())
129: {
130: SPFile page = web.GetFile("Source_Folder_Name/Source_Page");
131: SPLimitedWebPartManager webPartManager = page.GetLimitedWebPartManager(PersonalizationScope.Shared);
132: // SPWeb object webPartManager.Web leaked
133: } // SPWeb object web.Dispose() automatically called
134: } // SPSite object siteCollection.Dispose() automatically called
135: }
136:
137: void SPLimitedWebPartManagerNoLeak()
138: {
139: using (SPSite siteCollection = new SPSite("http://moss"))
140: {
141: using (SPWeb web = siteCollection.OpenWeb())
142: {
143: SPFile page = web.GetFile("Source_Folder_Name/Source_Page");
144: using (SPLimitedWebPartManager webPartManager = page.GetLimitedWebPartManager(PersonalizationScope.Shared))
145: {
146: try
147: {
148: // …
149: }
150: finally
151: {
152: webPartManager.Web.Dispose();
153: }
154: }
155: } // SPWeb object web.Dispose() automatically called
156: } // SPSite object siteCollection.Dispose() automatically called
157: }
158:
159: void WebsLeak()
160: {
161: using (SPSite siteCollection = new SPSite("http://moss"))
162: {
163: using (SPWeb outerWeb = siteCollection.OpenWeb())
164: {
165: foreach (SPWeb innerWeb in outerWeb.Webs)
166: {
167: // SPWeb innerWeb leak
168: }
169: } // SPWeb object outerWeb.Dispose() automatically called
170: } // SPSite object siteCollection.Dispose() automatically called
171: }
172:
173: void WebsNoLeak()
174: {
175: using (SPSite siteCollection = new SPSite("http://moss"))
176: {
177: using (SPWeb outerWeb = siteCollection.OpenWeb())
178: {
179: foreach (SPWeb innerWeb in outerWeb.Webs)
180: {
181: try
182: //should be 1st statement after foreach
183: {
184: // …
185: }
186: finally
187: {
188: if (innerWeb != null)
189: innerWeb.Dispose();
190: }
191: }
192: } // SPWeb object outerWeb.Dispose() automatically called
193: } // SPSite object siteCollection.Dispose() automatically called
194: }
195:
196: void WebsAddLeak(string strWebUrl)
197: {
198: using (SPSite siteCollection = new SPSite("http://moss"))
199: {
200: using (SPWeb web = siteCollection.OpenWeb())
201: {
202: SPWeb addedWeb = web.Webs.Add(strWebUrl); // will leak
203: } // SPWeb object web.Dispose() automatically called
204: } // SPSite object siteCollection.Dispose() automatically called
205: }
206:
207: void WebsAddNoLeak(string strWebUrl)
208: {
209: using (SPSite siteCollection = new SPSite("http://moss"))
210: {
211: using (SPWeb web = siteCollection.OpenWeb())
212: {
213: using (SPWeb addedWeb = web.Webs.Add(strWebUrl))
214: {
215: //..
216: }
217: } // SPWeb object web.Dispose() automatically called
218: } // SPSite object siteCollection.Dispose() automatically called
219: }
220:
221: void SPWebCollectionAddLeak(string strWebUrl)
222: {
223: using (SPSite siteCollection = new SPSite("http://moss"))
224: {
225: using (SPWeb outerWeb = siteCollection.OpenWeb())
226: {
227: SPWebCollection webCollection = siteCollection.AllWebs; // no AllWebs leak just getting reference
228: SPWeb innerWeb = webCollection.Add(strWebUrl); // must dispose of innerWeb
229: // innerWeb Leak
230: } // SPWeb object outerWeb.Dispose() automatically called
231: } // SPSite object siteCollection.Dispose() automatically called
232: }
233:
234: void SPWebCollectionAddNoLeak(string strWebUrl)
235: {
236: using (SPSite siteCollection = new SPSite("http://moss"))
237: {
238: using (SPWeb outerWeb = siteCollection.OpenWeb())
239: {
240: SPWebCollection webCollection = siteCollection.AllWebs; // no AllWebs leak just getting reference
241: using (SPWeb innerWeb = webCollection.Add(strWebUrl))
242: {
243: //…
244: }
245: } // SPWeb object outerWeb.Dispose() automatically called
246: } // SPSite object siteCollection.Dispose() automatically called
247: }
248:
249: void SPControlBADPractice()
250: {
251: HttpContext Context = null;
252: SPSite siteCollection = SPControl.GetContextSite(Context);
253: siteCollection.Dispose(); // DO NOT DO THIS
254: SPWeb web = SPControl.GetContextWeb(Context);
255: web.Dispose(); // DO NOT DO THIS
256: }
257:
258: void SPControlBestPractice()
259: {
260: HttpContext Context = null;
261: SPSite siteCollection = SPControl.GetContextSite(Context);
262: SPWeb web = SPControl.GetContextWeb(Context);
263: // Do NOT call Dispose()
264: }
265:
266: void SPContextBADPractice()
267: {
268: SPSite siteCollection = SPContext.Current.Site;
269: siteCollection.Dispose(); // DO NOT DO THIS
270: SPWeb web = SPContext.Current.Web;
271: web.Dispose(); // DO NOT DO THIS
272: }
273:
274: void SPContextBestPractice()
275: {
276: SPSite siteCollection = SPContext.Current.Site;
277: SPWeb web = SPContext.Current.Web;
278: // Do NOT call Dispose()
279: }
280:
281: void PublishingWebCollectionLeak()
282: {
283: using (SPSite siteCollection = new SPSite("http://moss"))
284: {
285: using (SPWeb web = siteCollection.OpenWeb())
286: {
287: // passing in web you own, no dispose needed on outerPubWeb
288: PublishingWeb outerPubWeb = PublishingWeb.GetPublishingWeb(web);
289:
290: PublishingWebCollection pubWebCollection = outerPubWeb.GetPublishingWebs();
291: foreach (PublishingWeb innerPubWeb in pubWebCollection)
292: {
293: // innerPubWeb leak
294: }
295:
296: // PublishingWeb will leak for each innerPubWeb referenced
297: } // SPWeb object web.Dispose() automatically called
298: } // SPSite object siteCollection.Dispose() automatically called
299: }
300:
301: void PublishingWebCollectionNoLeak()
302: {
303: using (SPSite siteCollection = new SPSite("http://moss"))
304: {
305: using (SPWeb web = siteCollection.OpenWeb())
306: {
307: // passing in web you own, no dispose needed on outerPubWeb
308: PublishingWeb outerPubWeb = PublishingWeb.GetPublishingWeb(web);
309: PublishingWebCollection pubWebCollection = outerPubWeb.GetPublishingWebs();
310: foreach (PublishingWeb innerPubWeb in pubWebCollection)
311: {
312: try
313: {
314: // …
315: }
316: finally
317: {
318: if (innerPubWeb != null)
319: innerPubWeb.Close();
320: }
321: }
322: // outerPubWeb.Close(); not needed and if called will log warning in ULS log
323: } // SPWeb object web.Dispose() automatically called
324: } // SPSite object siteCollection.Dispose() automatically called
325: }
326:
327: void GetPublishingWebNoLeak()
328: {
329: using (SPSite siteCollection = new SPSite("http://moss"))
330: {
331: using (SPWeb web = siteCollection.OpenWeb())
332: {
333: // passing in web you own, no dispose needed on singlePubWeb
334: PublishingWeb singlePubWeb = PublishingWeb.GetPublishingWeb(web);
335: } // SPWeb object web.Dispose() automatically called
336: } // SPSite object siteCollection.Dispose() automatically called
337: }
338:
339: void GetVariationLeak()
340: {
341: using (SPSite siteCollection = new SPSite("http://moss"))
342: {
343: using (SPWeb web = siteCollection.OpenWeb())
344: {
345: PublishingWeb publishingWeb = PublishingWeb.GetPublishingWeb(web); // Passing in web so no Close() needed
346: VariationLabel variationLabel = Variations.Current.UserAccessibleLabels[0];
347: PublishingWeb variationPublishingWeb = publishingWeb.GetVariation(variationLabel); // must be Closed()
348: // …
349: } // SPWeb object web.Dispose() automatically called
350: } // SPSite object siteCollection.Dispose() automatically called
351: }
352:
353: void GetVariationNoLeak()
354: {
355: using (SPSite siteCollection = new SPSite("http://moss"))
356: {
357: using (SPWeb web = siteCollection.OpenWeb())
358: {
359: PublishingWeb variationPublishingWeb = null;
360: try
361: {
362: PublishingWeb publishingWeb = PublishingWeb.GetPublishingWeb(web); // Passing in web so no Close() needed
363: VariationLabel variationLabel = Variations.Current.UserAccessibleLabels[0];
364: variationPublishingWeb = publishingWeb.GetVariation(variationLabel); // must be Closed()
365: // …
366: }
367: finally
368: {
369: if (variationPublishingWeb != null)
370: variationPublishingWeb.Close();
371: }
372: } // SPWeb object outerWeb.Dispose() automatically called
373: } // SPSite object siteCollection.Dispose() automatically called
374: }
375:
376: void PersonalSiteLeak()
377: {
378: // open a site collection
379: using (SPSite siteCollection = new SPSite("http://moss"))
380: {
381: UserProfileManager profileManager = new UserProfileManager(ServerContext.GetContext(siteCollection));
382: UserProfile profile = profileManager.GetUserProfile("domain\\username");
383: SPSite personalSite = profile.PersonalSite; // will leak
384: }
385: }
386:
387: void PersonalSiteNoLeak()
388: {
389: // open a site collection
390: using (SPSite siteCollection = new SPSite("http://moss"))
391: {
392: UserProfileManager profileManager = new UserProfileManager(ServerContext.GetContext(siteCollection));
393: UserProfile profile = profileManager.GetUserProfile("domain\\username");
394: using (SPSite personalSite = profile.PersonalSite)
395: {
396:
397: // …
398: }
399: }
400: }
401:
402: void SPSiteCollectionIndexerLeak()
403: {
404: using (SPSite siteCollectionOuter = new SPSite("http://moss"))
405: {
406: SPWebApplication webApp = siteCollectionOuter.WebApplication;
407: SPSiteCollection siteCollections = webApp.Sites;
408:
409:
410: SPSite siteCollectionInner = siteCollections[0];
411: // SPSite siteCollectionInner leak
412: } // SPSite object siteCollectionOuter.Dispose() automatically called
413: }
414:
415: void SPSiteCollectionIndexerNoLeak()
416: {
417: using (SPSite siteCollectionOuter = new SPSite("http://moss"))
418: {
419: SPSite siteCollectionInner = null;
420: try
421: {
422: SPWebApplication webApp = siteCollectionOuter.WebApplication;
423: SPSiteCollection siteCollections = webApp.Sites;
424:
425:
426: siteCollectionInner = siteCollections[0];
427: }
428: finally
429: {
430: if (siteCollectionInner != null)
431: siteCollectionInner.Dispose();
432: }
433: } // SPSite object siteCollectionOuter.Dispose() automatically called
434: }
435:
436: void SPSiteCollectionForEachLeak()
437: {
438: using (SPSite siteCollectionOuter = new SPSite("http://moss"))
439: {
440: SPWebApplication webApp = siteCollectionOuter.WebApplication;
441: SPSiteCollection siteCollections = webApp.Sites;
442:
443: foreach (SPSite siteCollectionInner in siteCollections)
444: {
445: // SPSite siteCollectionInner leak
446: }
447: } // SPSite object siteCollectionOuter.Dispose() automatically called
448: }
449:
450: void SPSiteCollectionForEachNoLeak()
451: {
452: using (SPSite siteCollectionOuter = new SPSite("http://moss"))
453: {
454: SPWebApplication webApp = siteCollectionOuter.WebApplication;
455: SPSiteCollection siteCollections = webApp.Sites;
456:
457:
458: foreach (SPSite siteCollectionInner in siteCollections)
459: {
460: try
461: {
462: // …
463: }
464: finally
465: {
466: if (siteCollectionInner != null)
467: siteCollectionInner.Dispose();
468: }
469: }
470: } // SPSite object siteCollectionOuter.Dispose() automatically called
471: }
472:
473: void SPSiteCollectionAddLeak()
474: {
475: SPWebApplication webApp = new SPSite("http://moss").WebApplication;
476: SPSiteCollection siteCollections = webApp.Sites;
477: SPSite siteCollection = siteCollections.Add("sites/myNewSiteCollection", "DOMAIN\\User", "roger.lamb@litwareinc.com");
478: // SPSite siteCollection leak
479: }
480:
481: void SPSiteCollectionAddNoLeak()
482: {
483: SPWebApplication webApp = new SPSite("http://moss").WebApplication;
484: SPSiteCollection siteCollections = webApp.Sites;
485: using (SPSite siteCollection = siteCollections.Add("sites/myNewSiteCollection", "DOMAIN\\User", "roger.lamb@litwareinc.com"))
486: {
487: } // SPSite object siteCollection.Dispose() automatically called
488: }
489:
490: public class CrossMethodLeak
491: {
492: private SPSite _siteCollection = null;
493: private SPWeb _web = null;
494:
495: public void MethodA()
496: {
497: _siteCollection = new SPSite("http://moss");
498: _web = _siteCollection.OpenWeb();
499: }
500:
501: public void MethodB()
502: {
503: if (_web != null)
504: {
505: string title = _web.Title;
506: }
507: }
508:
509: public void MethodC()
510: {
511: if (_web != null)
512: {
513: string name = _web.Name;
514: }
515: }
516: }
517: }
518: }
Alors un conseil, en attendant que ce soit corrigé/confirmé, ne considérez pas SPDisposeCheck comme parole d'évangile.