com.kylin.di 1.0.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/.github/workflows/publish.yml +8 -4
  2. package/.omc/project-memory.json +229 -0
  3. package/.omc/state/hud-state.json +6 -0
  4. package/README.md +1 -1
  5. package/Runtime/Kylin.DI.asmdef +3 -1
  6. package/package.json +10 -4
  7. package/Runtime/Debug/ClosureAnalyzer.cs +0 -377
  8. package/Runtime/Debug/ClosureAnalyzer.cs.meta +0 -2
  9. package/Runtime/Debug/ClosureProfilerWindow.cs +0 -435
  10. package/Runtime/Debug/ClosureProfilerWindow.cs.meta +0 -2
  11. package/Runtime/Debug/SubscriberInfo.cs +0 -661
  12. package/Runtime/Debug/SubscriberInfo.cs.meta +0 -3
  13. package/Runtime/Debug.meta +0 -3
  14. package/Runtime/SubscribableProperty/Reaction.cs +0 -61
  15. package/Runtime/SubscribableProperty/Reaction.cs.meta +0 -2
  16. package/Runtime/SubscribableProperty/SubscribableCollection.cs +0 -325
  17. package/Runtime/SubscribableProperty/SubscribableCollection.cs.meta +0 -3
  18. package/Runtime/SubscribableProperty/SubscribableCollectionExtensions.cs +0 -24
  19. package/Runtime/SubscribableProperty/SubscribableCollectionExtensions.cs.meta +0 -3
  20. package/Runtime/SubscribableProperty/SubscribableCommand.cs +0 -52
  21. package/Runtime/SubscribableProperty/SubscribableCommand.cs.meta +0 -2
  22. package/Runtime/SubscribableProperty/SubscribableDictionary.cs +0 -350
  23. package/Runtime/SubscribableProperty/SubscribableDictionary.cs.meta +0 -3
  24. package/Runtime/SubscribableProperty/SubscribableProperty.cs +0 -119
  25. package/Runtime/SubscribableProperty/SubscribableProperty.cs.meta +0 -2
  26. package/Runtime/SubscribableProperty/SubscribablePropertyExtensions.cs +0 -39
  27. package/Runtime/SubscribableProperty/SubscribablePropertyExtensions.cs.meta +0 -3
  28. package/Runtime/SubscribableProperty/SubscribablePropertyLinq.cs +0 -86
  29. package/Runtime/SubscribableProperty/SubscribablePropertyLinq.cs.meta +0 -2
  30. package/Runtime/SubscribableProperty.meta +0 -8
@@ -8,6 +8,9 @@ on:
8
8
  jobs:
9
9
  publish:
10
10
  runs-on: ubuntu-latest
11
+ permissions:
12
+ contents: read
13
+ id-token: write
11
14
  steps:
12
15
  - uses: actions/checkout@v4
13
16
 
@@ -16,7 +19,8 @@ jobs:
16
19
  node-version: '20'
17
20
  registry-url: 'https://registry.npmjs.org'
18
21
 
19
- - name: Publish package
20
- run: npm publish
21
- env:
22
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
22
+ - name: Upgrade npm for OIDC support
23
+ run: npm install -g npm@latest
24
+
25
+ - name: Publish with trusted publishing
26
+ run: npm publish --access public
@@ -0,0 +1,229 @@
1
+ {
2
+ "version": "1.0.0",
3
+ "lastScanned": 1773710696675,
4
+ "projectRoot": "C:\\ProjectControl\\KDIPackage",
5
+ "techStack": {
6
+ "languages": [
7
+ {
8
+ "name": "JavaScript/TypeScript",
9
+ "version": null,
10
+ "confidence": "high",
11
+ "markers": [
12
+ "package.json"
13
+ ]
14
+ }
15
+ ],
16
+ "frameworks": [],
17
+ "packageManager": "npm",
18
+ "runtime": null
19
+ },
20
+ "build": {
21
+ "buildCommand": null,
22
+ "testCommand": null,
23
+ "lintCommand": null,
24
+ "devCommand": null,
25
+ "scripts": {}
26
+ },
27
+ "conventions": {
28
+ "namingStyle": null,
29
+ "importStyle": null,
30
+ "testPattern": null,
31
+ "fileOrganization": null
32
+ },
33
+ "structure": {
34
+ "isMonorepo": false,
35
+ "workspaces": [],
36
+ "mainDirectories": [],
37
+ "gitBranches": {
38
+ "defaultBranch": "master",
39
+ "branchingStrategy": null
40
+ }
41
+ },
42
+ "customNotes": [],
43
+ "directoryMap": {
44
+ "Runtime": {
45
+ "path": "Runtime",
46
+ "purpose": null,
47
+ "fileCount": 8,
48
+ "lastAccessed": 1773710696650,
49
+ "keyFiles": [
50
+ "Attributes.meta",
51
+ "Core.meta",
52
+ "Debug.meta",
53
+ "DI.meta",
54
+ "Kylin.DI.asmdef"
55
+ ]
56
+ }
57
+ },
58
+ "hotPaths": [
59
+ {
60
+ "path": "",
61
+ "accessCount": 5,
62
+ "lastAccessed": 1773710728288,
63
+ "type": "directory"
64
+ },
65
+ {
66
+ "path": "README.md",
67
+ "accessCount": 2,
68
+ "lastAccessed": 1773711146365,
69
+ "type": "file"
70
+ },
71
+ {
72
+ "path": "package.json",
73
+ "accessCount": 1,
74
+ "lastAccessed": 1773710732915,
75
+ "type": "file"
76
+ },
77
+ {
78
+ "path": "Runtime\\Kylin.DI.asmdef",
79
+ "accessCount": 1,
80
+ "lastAccessed": 1773710733554,
81
+ "type": "file"
82
+ },
83
+ {
84
+ "path": "Runtime\\DI\\KDI.cs",
85
+ "accessCount": 1,
86
+ "lastAccessed": 1773710733804,
87
+ "type": "file"
88
+ },
89
+ {
90
+ "path": "Runtime\\DI\\Scope.cs",
91
+ "accessCount": 1,
92
+ "lastAccessed": 1773710734108,
93
+ "type": "file"
94
+ },
95
+ {
96
+ "path": "Runtime\\DI\\Registration.cs",
97
+ "accessCount": 1,
98
+ "lastAccessed": 1773710734544,
99
+ "type": "file"
100
+ },
101
+ {
102
+ "path": "Runtime\\Core\\LifetimeScope.cs",
103
+ "accessCount": 1,
104
+ "lastAccessed": 1773710734976,
105
+ "type": "file"
106
+ },
107
+ {
108
+ "path": "Runtime\\Core\\DIBehaviour.cs",
109
+ "accessCount": 1,
110
+ "lastAccessed": 1773710735204,
111
+ "type": "file"
112
+ },
113
+ {
114
+ "path": "Runtime\\DI\\DependencyBuilder.cs",
115
+ "accessCount": 1,
116
+ "lastAccessed": 1773710739245,
117
+ "type": "file"
118
+ },
119
+ {
120
+ "path": "Runtime\\DI\\DependencyInjector.cs",
121
+ "accessCount": 1,
122
+ "lastAccessed": 1773710739574,
123
+ "type": "file"
124
+ },
125
+ {
126
+ "path": "Runtime\\DI\\InstanceFactory.cs",
127
+ "accessCount": 1,
128
+ "lastAccessed": 1773710740017,
129
+ "type": "file"
130
+ },
131
+ {
132
+ "path": "Runtime\\DI\\ScopeBuilder.cs",
133
+ "accessCount": 1,
134
+ "lastAccessed": 1773710740465,
135
+ "type": "file"
136
+ },
137
+ {
138
+ "path": "Runtime\\DI\\ScopeExtensions.cs",
139
+ "accessCount": 1,
140
+ "lastAccessed": 1773710740905,
141
+ "type": "file"
142
+ },
143
+ {
144
+ "path": "Runtime\\Attributes\\InjectAttribute.cs",
145
+ "accessCount": 1,
146
+ "lastAccessed": 1773710741924,
147
+ "type": "file"
148
+ },
149
+ {
150
+ "path": "Runtime\\Attributes\\ViewModelAttribute.cs",
151
+ "accessCount": 1,
152
+ "lastAccessed": 1773710742234,
153
+ "type": "file"
154
+ },
155
+ {
156
+ "path": "Runtime\\Update\\UpdateLoopManager.cs",
157
+ "accessCount": 1,
158
+ "lastAccessed": 1773710742681,
159
+ "type": "file"
160
+ },
161
+ {
162
+ "path": "Runtime\\SubscribableProperty\\SubscribableProperty.cs",
163
+ "accessCount": 1,
164
+ "lastAccessed": 1773710742957,
165
+ "type": "file"
166
+ },
167
+ {
168
+ "path": "CLAUDE.md",
169
+ "accessCount": 1,
170
+ "lastAccessed": 1773710790027,
171
+ "type": "file"
172
+ },
173
+ {
174
+ "path": "Runtime\\SubscribableProperty\\SubscribableCollection.cs",
175
+ "accessCount": 1,
176
+ "lastAccessed": 1773710989419,
177
+ "type": "file"
178
+ },
179
+ {
180
+ "path": "Runtime\\SubscribableProperty\\SubscribablePropertyExtensions.cs",
181
+ "accessCount": 1,
182
+ "lastAccessed": 1773710989888,
183
+ "type": "file"
184
+ },
185
+ {
186
+ "path": "Runtime\\SubscribableProperty\\SubscribablePropertyLinq.cs",
187
+ "accessCount": 1,
188
+ "lastAccessed": 1773710990457,
189
+ "type": "file"
190
+ },
191
+ {
192
+ "path": "Runtime\\SubscribableProperty\\SubscribableCommand.cs",
193
+ "accessCount": 1,
194
+ "lastAccessed": 1773710990803,
195
+ "type": "file"
196
+ },
197
+ {
198
+ "path": "Runtime\\SubscribableProperty\\SubscribableDictionary.cs",
199
+ "accessCount": 1,
200
+ "lastAccessed": 1773710991251,
201
+ "type": "file"
202
+ },
203
+ {
204
+ "path": "Runtime\\SubscribableProperty\\SubscribableCollectionExtensions.cs",
205
+ "accessCount": 1,
206
+ "lastAccessed": 1773710991698,
207
+ "type": "file"
208
+ },
209
+ {
210
+ "path": "Runtime\\Update\\IUpdatable.cs",
211
+ "accessCount": 1,
212
+ "lastAccessed": 1773710992139,
213
+ "type": "file"
214
+ },
215
+ {
216
+ "path": "Runtime\\Update\\IUpdatePriority.cs",
217
+ "accessCount": 1,
218
+ "lastAccessed": 1773710992657,
219
+ "type": "file"
220
+ },
221
+ {
222
+ "path": "Runtime\\Debug\\ClosureAnalyzer.cs",
223
+ "accessCount": 1,
224
+ "lastAccessed": 1773710993007,
225
+ "type": "file"
226
+ }
227
+ ],
228
+ "userDirectives": []
229
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "timestamp": "2026-03-17T01:25:25.771Z",
3
+ "backgroundTasks": [],
4
+ "sessionStartTimestamp": "2026-03-17T01:24:56.369Z",
5
+ "sessionId": "33f97ae5d926a0dc"
6
+ }
package/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
  Unity 6 전용 Scope 기반 경량 DI 프레임워크. 필드 주입 전용, 계층적 Scope, 반응형 프로퍼티 내장.
4
4
 
5
5
  ```
6
- com.kylin.di v1.0.0 | Unity 6000.0+ | MIT License
6
+ com.kylin.di | Unity 6000.0+ | MIT License
7
7
  ```
8
8
 
9
9
  ---
@@ -1,7 +1,9 @@
1
1
  {
2
2
  "name": "Kylin.DI",
3
3
  "rootNamespace": "Kylin",
4
- "references": [],
4
+ "references": [
5
+ "Kylin.Subscribable"
6
+ ],
5
7
  "includePlatforms": [],
6
8
  "excludePlatforms": [],
7
9
  "allowUnsafeCode": false,
package/package.json CHANGED
@@ -1,19 +1,25 @@
1
1
  {
2
2
  "name": "com.kylin.di",
3
- "version": "1.0.0",
3
+ "version": "1.1.1",
4
4
  "displayName": "KDI (Kylin Dependency Injection)",
5
- "description": "Scope-based dependency injection framework for Unity 6. Field injection only, hierarchical scopes, built-in reactive properties.",
5
+ "description": "Scope-based dependency injection framework for Unity 6. Field injection only, hierarchical scopes.",
6
6
  "unity": "6000.0",
7
7
  "documentationUrl": "",
8
8
  "license": "MIT",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "https://github.com/ToolStorage/KDI"
12
+ },
9
13
  "keywords": [
10
14
  "dependency-injection",
11
15
  "di",
12
16
  "ioc",
13
- "scope",
14
- "reactive"
17
+ "scope"
15
18
  ],
16
19
  "author": {
17
20
  "name": "Kylin"
21
+ },
22
+ "dependencies": {
23
+ "com.kylin.subscribable": "1.0.0"
18
24
  }
19
25
  }
@@ -1,377 +0,0 @@
1
- using System;
2
- using System.Collections.Generic;
3
- using System.Linq;
4
- using System.Reflection;
5
- using UnityEngine;
6
-
7
- namespace Kylin.SubscribableProperty
8
- {
9
- /// <summary>
10
- /// 클로저 캡처 정보
11
- /// </summary>
12
- public class ClosureCaptureInfo
13
- {
14
- public WeakReference ClosureRef { get; }
15
- public Type ClosureType { get; }
16
- public string ClosureTypeName { get; }
17
- public DateTime CaptureTime { get; }
18
- public string CaptureLocation { get; }
19
-
20
- // 캡처된 변수들
21
- public List<CapturedVariableInfo> CapturedVariables { get; }
22
-
23
- // 메모리 정보
24
- public long EstimatedMemoryBytes { get; private set; }
25
- public bool IsAlive => ClosureRef.IsAlive;
26
- public object Closure => ClosureRef.Target;
27
-
28
- // 구독 해제 정보
29
- public bool IsUnsubscribed { get; set; }
30
- public DateTime? UnsubscribeTime { get; set; }
31
- public TimeSpan? Lifetime => UnsubscribeTime.HasValue
32
- ? UnsubscribeTime.Value - CaptureTime
33
- : (DateTime.Now - CaptureTime);
34
-
35
- public ClosureCaptureInfo(object closure, string captureLocation)
36
- {
37
- ClosureRef = new WeakReference(closure);
38
- ClosureType = closure.GetType();
39
- ClosureTypeName = GetReadableTypeName(ClosureType);
40
- CaptureTime = DateTime.Now;
41
- CaptureLocation = captureLocation;
42
- CapturedVariables = new List<CapturedVariableInfo>();
43
-
44
- AnalyzeCapturedVariables();
45
- }
46
-
47
- private string GetReadableTypeName(Type type)
48
- {
49
- // <>c__DisplayClass1_0 → Closure_1_0
50
- if (type.Name.Contains("DisplayClass"))
51
- {
52
- var parts = type.Name.Split('_');
53
- if (parts.Length >= 3)
54
- {
55
- return $"Closure_{parts[^2]}_{parts[^1]}";
56
- }
57
- }
58
- return type.Name;
59
- }
60
-
61
- private void AnalyzeCapturedVariables()
62
- {
63
- if (!IsAlive) return;
64
-
65
- var closure = Closure;
66
- var fields = ClosureType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
67
-
68
- foreach (var field in fields)
69
- {
70
- try
71
- {
72
- var value = field.GetValue(closure);
73
- var varInfo = new CapturedVariableInfo(field, value);
74
- CapturedVariables.Add(varInfo);
75
- EstimatedMemoryBytes += varInfo.EstimatedMemoryBytes;
76
- }
77
- catch (Exception ex)
78
- {
79
- Debug.LogWarning($"[ClosureAnalyzer] Failed to analyze field {field.Name}: {ex.Message}");
80
- }
81
- }
82
- }
83
-
84
- public void MarkUnsubscribed()
85
- {
86
- IsUnsubscribed = true;
87
- UnsubscribeTime = DateTime.Now;
88
- }
89
-
90
- public void RefreshMemoryInfo()
91
- {
92
- EstimatedMemoryBytes = 0;
93
- foreach (var varInfo in CapturedVariables)
94
- {
95
- varInfo.RefreshMemoryInfo();
96
- EstimatedMemoryBytes += varInfo.EstimatedMemoryBytes;
97
- }
98
- }
99
- }
100
-
101
- /// <summary>
102
- /// 캡처된 개별 변수 정보
103
- /// </summary>
104
- public class CapturedVariableInfo
105
- {
106
- public string FieldName { get; }
107
- public Type FieldType { get; }
108
- public string FieldTypeName { get; }
109
- public WeakReference ValueRef { get; }
110
- public bool IsReferenceType { get; }
111
- public long EstimatedMemoryBytes { get; private set; }
112
-
113
- // 위험도 평가
114
- public ClosureCaptureRisk RiskLevel { get; private set; }
115
- public string RiskDescription { get; private set; }
116
-
117
- public bool IsAlive => ValueRef?.IsAlive ?? false;
118
- public object Value => ValueRef?.Target;
119
-
120
- public CapturedVariableInfo(FieldInfo field, object value)
121
- {
122
- FieldName = CleanFieldName(field.Name);
123
- FieldType = field.FieldType;
124
- FieldTypeName = GetReadableTypeName(field.FieldType);
125
- IsReferenceType = !field.FieldType.IsValueType;
126
-
127
- if (value != null && IsReferenceType)
128
- {
129
- ValueRef = new WeakReference(value);
130
- }
131
-
132
- EstimateMemory(value);
133
- EvaluateRisk(field, value);
134
- }
135
-
136
- private string CleanFieldName(string fieldName)
137
- {
138
- // <>4__this → this
139
- if (fieldName.Contains("4__this"))
140
- return "this";
141
-
142
- // CS$<>8__locals1 → locals_1
143
- if (fieldName.Contains("CS$"))
144
- return "locals";
145
-
146
- return fieldName.TrimStart('<', '>');
147
- }
148
-
149
- private string GetReadableTypeName(Type type)
150
- {
151
- if (type.IsGenericType)
152
- {
153
- var name = type.Name.Split('`')[0];
154
- var args = string.Join(", ", type.GetGenericArguments().Select(t => t.Name));
155
- return $"{name}<{args}>";
156
- }
157
- return type.Name;
158
- }
159
-
160
- private void EstimateMemory(object value)
161
- {
162
- if (value == null)
163
- {
164
- EstimatedMemoryBytes = 0;
165
- return;
166
- }
167
-
168
- if (!IsReferenceType)
169
- {
170
- EstimatedMemoryBytes = System.Runtime.InteropServices.Marshal.SizeOf(FieldType);
171
- return;
172
- }
173
-
174
- // 참조 타입 메모리 추정
175
- EstimatedMemoryBytes = 8; // 참조 자체
176
-
177
- try
178
- {
179
- if (value is string str)
180
- {
181
- EstimatedMemoryBytes += str.Length * 2 + 24; // UTF-16 + 오버헤드
182
- }
183
- else if (value is Array array)
184
- {
185
- EstimatedMemoryBytes += array.Length * 8 + 24;
186
- }
187
- else if (value is System.Collections.ICollection collection)
188
- {
189
- EstimatedMemoryBytes += collection.Count * 8 + 40;
190
- }
191
- else if (value is MonoBehaviour || value is ScriptableObject)
192
- {
193
- EstimatedMemoryBytes += 1024; // Unity 객체 추정치
194
- }
195
- else
196
- {
197
- EstimatedMemoryBytes += 64; // 일반 객체 추정치
198
- }
199
- }
200
- catch
201
- {
202
- EstimatedMemoryBytes += 64;
203
- }
204
- }
205
-
206
- private void EvaluateRisk(FieldInfo field, object value)
207
- {
208
- RiskLevel = ClosureCaptureRisk.Low;
209
- RiskDescription = "안전";
210
-
211
- if (value == null) return;
212
-
213
- // this 캡처 (가장 위험)
214
- if (field.Name.Contains("4__this"))
215
- {
216
- RiskLevel = ClosureCaptureRisk.Critical;
217
- RiskDescription = "인스턴스 전체 캡처 - 모든 필드가 메모리에 유지됨";
218
- return;
219
- }
220
-
221
- // 큰 컬렉션
222
- if (value is System.Collections.ICollection collection && collection.Count > 100)
223
- {
224
- RiskLevel = ClosureCaptureRisk.High;
225
- RiskDescription = $"대용량 컬렉션 캡처 ({collection.Count}개 요소)";
226
- return;
227
- }
228
-
229
- // Unity 객체
230
- if (value is MonoBehaviour || value is ScriptableObject)
231
- {
232
- RiskLevel = ClosureCaptureRisk.High;
233
- RiskDescription = "Unity 컴포넌트 캡처 - 게임 오브젝트와 연결된 모든 데이터 유지";
234
- return;
235
- }
236
-
237
- // 큰 배열/버퍼
238
- if (value is Array array && array.Length > 1000)
239
- {
240
- RiskLevel = ClosureCaptureRisk.High;
241
- RiskDescription = $"대용량 배열 캡처 ({array.Length}개 요소, ~{EstimatedMemoryBytes / 1024}KB)";
242
- return;
243
- }
244
-
245
- // 중간 위험
246
- if (EstimatedMemoryBytes > 1024) // 1KB 이상
247
- {
248
- RiskLevel = ClosureCaptureRisk.Medium;
249
- RiskDescription = $"메모리 사용량 높음 (~{EstimatedMemoryBytes / 1024}KB)";
250
- return;
251
- }
252
-
253
- // 참조 타입이지만 작은 객체
254
- if (IsReferenceType)
255
- {
256
- RiskLevel = ClosureCaptureRisk.Low;
257
- RiskDescription = "작은 참조 타입 캡처";
258
- }
259
- }
260
-
261
- public void RefreshMemoryInfo()
262
- {
263
- if (IsAlive)
264
- {
265
- EstimateMemory(Value);
266
- }
267
- }
268
- }
269
-
270
- public enum ClosureCaptureRisk
271
- {
272
- Low, // 안전 (값 타입, 작은 참조)
273
- Medium, // 주의 (중간 크기 객체)
274
- High, // 위험 (큰 객체, Unity 컴포넌트)
275
- Critical // 매우 위험 (this 캡처)
276
- }
277
-
278
- /// <summary>
279
- /// 클로저 캡처 프로파일러
280
- /// </summary>
281
- public static class ClosureProfiler
282
- {
283
- private static readonly List<ClosureCaptureInfo> _captures = new List<ClosureCaptureInfo>();
284
- private static readonly object _lock = new object();
285
-
286
- public static bool IsEnabled =>
287
- #if UNITY_EDITOR
288
- ClosureProfilerWindow.IsWindowOpen && ClosureProfilerWindow.IsProfilingEnabled;
289
- #else
290
- false;
291
- #endif
292
-
293
- public static void RecordCapture(object closure, string location)
294
- {
295
- if (!IsEnabled) return;
296
- if (closure == null) return;
297
-
298
- // 컴파일러 생성 클로저인지 확인
299
- var typeName = closure.GetType().Name;
300
- if (!typeName.Contains("DisplayClass") && !typeName.Contains("<>c"))
301
- return;
302
-
303
- lock (_lock)
304
- {
305
- var info = new ClosureCaptureInfo(closure, location);
306
- _captures.Add(info);
307
- }
308
- }
309
-
310
- public static void RecordUnsubscribe(object closure)
311
- {
312
- if (closure == null) return;
313
-
314
- lock (_lock)
315
- {
316
- var info = _captures.FirstOrDefault(c =>
317
- c.IsAlive && ReferenceEquals(c.Closure, closure));
318
-
319
- if (info != null)
320
- {
321
- info.MarkUnsubscribed();
322
- }
323
- }
324
- }
325
-
326
- public static IEnumerable<ClosureCaptureInfo> GetAllCaptures()
327
- {
328
- lock (_lock)
329
- {
330
- // 죽은 클로저는 제거하지 않음 (히스토리 유지)
331
- return _captures.ToList();
332
- }
333
- }
334
-
335
- public static IEnumerable<ClosureCaptureInfo> GetActiveCaptures()
336
- {
337
- lock (_lock)
338
- {
339
- return _captures.Where(c => c.IsAlive && !c.IsUnsubscribed).ToList();
340
- }
341
- }
342
-
343
- public static void Clear()
344
- {
345
- lock (_lock)
346
- {
347
- _captures.Clear();
348
- }
349
- }
350
-
351
- public static (int total, int active, int unsubscribed, long totalMemory) GetStatistics()
352
- {
353
- lock (_lock)
354
- {
355
- var total = _captures.Count;
356
- var active = _captures.Count(c => c.IsAlive && !c.IsUnsubscribed);
357
- var unsubscribed = _captures.Count(c => c.IsUnsubscribed);
358
- var totalMemory = _captures
359
- .Where(c => c.IsAlive && !c.IsUnsubscribed)
360
- .Sum(c => c.EstimatedMemoryBytes);
361
-
362
- return (total, active, unsubscribed, totalMemory);
363
- }
364
- }
365
-
366
- public static void RefreshMemoryInfo()
367
- {
368
- lock (_lock)
369
- {
370
- foreach (var capture in _captures.Where(c => c.IsAlive))
371
- {
372
- capture.RefreshMemoryInfo();
373
- }
374
- }
375
- }
376
- }
377
- }
@@ -1,2 +0,0 @@
1
- fileFormatVersion: 2
2
- guid: c9b440301be532f4495ed50aac9d94d1