Skip to content

Commit c72b8a6

Browse files
committed
Introduce the TypeApiFactory to encapsulate the creation of the ITypeLibWrapper & ITypeInfoWrapper, making it easy to get them traced with appropriate flags. Redirect all the news into the factory. Also some cleanup of missed abstractions.
1 parent 22cf25e commit c72b8a6

File tree

7 files changed

+67
-17
lines changed

7 files changed

+67
-17
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#define TRACE_TYPEAPI
2+
3+
using System;
4+
using System.Runtime.InteropServices.ComTypes;
5+
using Rubberduck.VBEditor.ComManagement.TypeLibs.Abstract;
6+
7+
#if DEBUG && TRACE_TYPEAPI
8+
using Rubberduck.VBEditor.ComManagement.TypeLibs.DebugInternal;
9+
#endif
10+
11+
namespace Rubberduck.VBEditor.ComManagement.TypeLibs
12+
{
13+
internal static class TypeApiFactory
14+
{
15+
internal static ITypeLibWrapper GetTypeLibWrapper(IntPtr rawObjectPtr, bool addRef)
16+
{
17+
var wrapper = new TypeLibWrapper(rawObjectPtr, addRef);
18+
#if DEBUG && TRACE_TYPEAPI
19+
return new TypeLibWrapperTracer(wrapper);
20+
#else
21+
return wrapper;
22+
#endif
23+
}
24+
25+
internal static ITypeInfoWrapper GetTypeInfoWrapper(IntPtr rawObjectPtr, int? parentUserFormUniqueId = null)
26+
{
27+
var wrapper = new TypeInfoWrapper(rawObjectPtr, parentUserFormUniqueId);
28+
#if DEBUG && TRACE_TYPEAPI
29+
return new TypeInfoWrapperTracer(wrapper);
30+
#else
31+
return wrapper;
32+
#endif
33+
}
34+
35+
internal static ITypeInfoWrapper GetTypeInfoWrapper(ITypeInfo rawTypeInfo)
36+
{
37+
var wrapper = new TypeInfoWrapper(rawTypeInfo);
38+
#if DEBUG && TRACE_TYPEAPI
39+
return new TypeInfoWrapperTracer(wrapper);
40+
#else
41+
return wrapper;
42+
#endif
43+
}
44+
}
45+
}

Rubberduck.VBEEditor/ComManagement/TypeLibs/TypeInfoImplementedInterfacesCollection.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public override ITypeInfoWrapper GetItemByIndex(int index)
2424
_parent.GetRefTypeOfImplType(index, out var href);
2525
_parent.GetRefTypeInfo(href, out var ti);
2626

27-
return new TypeInfoWrapper(ti);
27+
return TypeApiFactory.GetTypeInfoWrapper(ti);
2828
}
2929

3030
/// <summary>

Rubberduck.VBEEditor/ComManagement/TypeLibs/TypeInfoWrapper.cs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ private void InitCommon()
133133
if (!ComHelper.HRESULT_FAILED(hr))
134134
{
135135
// We have to wrap the ITypeLib returned by GetContainingTypeLib
136-
_container = new TypeLibWrapper(typeLibPtr.Value, addRef: false);
136+
_container = (TypeLibInternalSelfMarshalForwarderBase)TypeApiFactory.GetTypeLibWrapper(typeLibPtr.Value, addRef: false);
137137
ContainerIndex = containerTypeLibIndex.Value;
138138
}
139139
else
@@ -180,7 +180,11 @@ private void InitFromRawPointer(IntPtr rawObjectPtr, bool addRef)
180180
DetectUserFormClass();
181181
}
182182

183-
public TypeInfoWrapper(ComTypes.ITypeInfo rawTypeInfo)
183+
/// <summary>
184+
/// Constructor
185+
/// </summary>
186+
/// <param name="rawTypeInfo">The ITypeInfo object to be wrapped. It will be checked if it's already wrapped to avoid double-wraping.</param>
187+
internal TypeInfoWrapper(ComTypes.ITypeInfo rawTypeInfo)
184188
{
185189
if ((rawTypeInfo as TypeInfoInternalSelfMarshalForwarderBase) != null)
186190
{
@@ -200,7 +204,7 @@ public TypeInfoWrapper(ComTypes.ITypeInfo rawTypeInfo)
200204
/// </summary>
201205
/// <param name="rawObjectPtr">The raw unmanaged pointer to the ITypeInfo. This class takes ownership, and will call Marshall.Release() on it upon disposal.</param>
202206
/// <param name="parentUserFormUniqueId">used internally for providing a name for UserForm base classes</param>
203-
public TypeInfoWrapper(IntPtr rawObjectPtr, int? parentUserFormUniqueId = null)
207+
internal TypeInfoWrapper(IntPtr rawObjectPtr, int? parentUserFormUniqueId = null)
204208
{
205209
// base classes of VBE UserForms cause an access violation on calling GetDocumentation(MEMBERID_NIL)
206210
// so we have to detect UserForm parents, and ensure GetDocumentation(MEMBERID_NIL) never gets through
@@ -296,7 +300,7 @@ private void DetectUserFormClass()
296300
}
297301
}
298302

299-
public int GetSafeRefTypeInfo(int hRef, out TypeInfoWrapper outTI)
303+
public int GetSafeRefTypeInfo(int hRef, out ITypeInfoWrapper outTI)
300304
{
301305
outTI = null;
302306

@@ -305,7 +309,7 @@ public int GetSafeRefTypeInfo(int hRef, out TypeInfoWrapper outTI)
305309
var hr = _target_ITypeInfo.GetRefTypeInfo(hRef, typeInfoPtr.Address);
306310
if (ComHelper.HRESULT_FAILED(hr)) return HandleBadHRESULT(hr);
307311

308-
var outVal = new TypeInfoWrapper(typeInfoPtr.Value, IsUserFormBaseClass ? (int?)hRef : null); // takes ownership of the COM reference
312+
var outVal = TypeApiFactory.GetTypeInfoWrapper(typeInfoPtr.Value, IsUserFormBaseClass ? (int?)hRef : null); // takes ownership of the COM reference
309313
_cachedReferencedTypeInfos = _cachedReferencedTypeInfos ?? new DisposableList<ITypeInfoWrapper>();
310314
_cachedReferencedTypeInfos.Add(outVal);
311315
outTI = outVal;

Rubberduck.VBEEditor/ComManagement/TypeLibs/TypeLibVBEExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ public ITypeLibWrapper GetVBEReferenceTypeLibByIndex(int index)
165165
{
166166
throw new ArgumentException("Reference TypeLib not available - probably a missing reference.");
167167
}
168-
return new TypeLibWrapper(referenceTypeLibPtr, addRef: false);
168+
return TypeApiFactory.GetTypeLibWrapper(referenceTypeLibPtr, addRef: false);
169169
}
170170

171171
public ITypeLibReference GetVBEReferenceByGuid(Guid referenceGuid)

Rubberduck.VBEEditor/ComManagement/TypeLibs/TypeLibWrapper.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ internal static ITypeLibWrapper FromVBProject(IVBProject vbProject)
108108
{
109109
// Now we've got the references object, we can read the internal object structure to grab the ITypeLib
110110
var internalReferencesObj = StructHelper.ReadComObjectStructure<VBEReferencesObj>(references.Target);
111-
return new TypeLibWrapper(internalReferencesObj._typeLib, addRef: true);
111+
return TypeApiFactory.GetTypeLibWrapper(internalReferencesObj._typeLib, addRef: true);
112112
}
113113
}
114114

@@ -132,7 +132,7 @@ private void InitFromRawPointer(IntPtr rawObjectPtr, bool addRef)
132132
/// direct memory read. Setting the parameter will effect an IUnknown::AddRef
133133
/// on the pointer.
134134
/// </param>
135-
public TypeLibWrapper(IntPtr rawObjectPtr, bool addRef)
135+
internal TypeLibWrapper(IntPtr rawObjectPtr, bool addRef)
136136
{
137137
InitFromRawPointer(rawObjectPtr, addRef);
138138
}
@@ -147,7 +147,7 @@ public override void Dispose()
147147
_typeLibPointer.Dispose();
148148
}
149149

150-
public int GetSafeTypeInfoByIndex(int index, out TypeInfoWrapper outTI)
150+
public int GetSafeTypeInfoByIndex(int index, out ITypeInfoWrapper outTI)
151151
{
152152
outTI = null;
153153

@@ -159,7 +159,7 @@ public int GetSafeTypeInfoByIndex(int index, out TypeInfoWrapper outTI)
159159
return HandleBadHRESULT(hr);
160160
}
161161

162-
var outVal = new TypeInfoWrapper(typeInfoPtr.Value);
162+
var outVal = TypeApiFactory.GetTypeInfoWrapper(typeInfoPtr.Value);
163163
_cachedTypeInfos = _cachedTypeInfos ?? new DisposableList<ITypeInfoWrapper>();
164164
_cachedTypeInfos.Add(outVal);
165165
outTI = outVal;
@@ -241,7 +241,7 @@ public override int GetTypeInfoOfGuid(ref Guid guid, IntPtr ppTInfo)
241241
if (ComHelper.HRESULT_FAILED(hr)) return HandleBadHRESULT(hr);
242242

243243
var pTInfo = RdMarshal.ReadIntPtr(ppTInfo);
244-
using (var outVal = new TypeInfoWrapper(pTInfo)) // takes ownership of the COM reference [pTInfo]
244+
using (var outVal = TypeApiFactory.GetTypeInfoWrapper(pTInfo)) // takes ownership of the COM reference [pTInfo]
245245
{
246246
RdMarshal.WriteIntPtr(ppTInfo, outVal.GetCOMReferencePtr());
247247

Rubberduck.VBEEditor/ComManagement/TypeLibs/Unmanaged/VBETypeLibsIterator.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Collections;
33
using System.Collections.Generic;
44
using System.Runtime.InteropServices;
5+
using Rubberduck.VBEditor.ComManagement.TypeLibs.Abstract;
56

67
namespace Rubberduck.VBEditor.ComManagement.TypeLibs.Unmanaged
78
{
@@ -22,7 +23,7 @@ internal struct VBETypeLibObj
2223
/// <summary>
2324
/// An enumerable class for iterating over the double linked list of ITypeLibs provided by the VBE
2425
/// </summary>
25-
internal sealed class VBETypeLibsIterator : IEnumerable<TypeLibWrapper>, IEnumerator<TypeLibWrapper>
26+
internal sealed class VBETypeLibsIterator : IEnumerable<ITypeLibWrapper>, IEnumerator<ITypeLibWrapper>
2627
{
2728
private IntPtr _currentTypeLibPtr;
2829
private VBETypeLibObj _currentTypeLibStruct;
@@ -41,10 +42,10 @@ public void Dispose()
4142
}
4243

4344
IEnumerator IEnumerable.GetEnumerator() => this;
44-
public IEnumerator<TypeLibWrapper> GetEnumerator() => this;
45+
public IEnumerator<ITypeLibWrapper> GetEnumerator() => this;
4546

46-
TypeLibWrapper IEnumerator<TypeLibWrapper>.Current => new TypeLibWrapper(_currentTypeLibPtr, addRef: true);
47-
object IEnumerator.Current => new TypeLibWrapper(_currentTypeLibPtr, addRef: true);
47+
ITypeLibWrapper IEnumerator<ITypeLibWrapper>.Current => TypeApiFactory.GetTypeLibWrapper(_currentTypeLibPtr, addRef: true);
48+
object IEnumerator.Current => TypeApiFactory.GetTypeLibWrapper(_currentTypeLibPtr, addRef: true);
4849

4950
public void Reset() // walk back to the first project in the chain
5051
{

Rubberduck.VBEEditor/ComManagement/TypeLibs/VBETypeLibsAccessor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ internal struct VBEReferencesObj
3434
/// Make sure you call VBETypeLibsAccessor.Dispose() as soon as you have done what you need to do with it.
3535
/// Once control returns back to the VBE, you must assume that all the ITypeLib/ITypeInfo pointers are now invalid.
3636
/// </remarks>
37-
internal class VBETypeLibsAccessor : DisposableList<TypeLibWrapper>
37+
internal class VBETypeLibsAccessor : DisposableList<ITypeLibWrapper>
3838
{
3939
internal VBETypeLibsAccessor(IVBE ide)
4040
{

0 commit comments

Comments
 (0)