6

我想枚举字符串实习生池中的字符串。

也就是说,我想得到这样的所有实例的s列表string

string.IsInterned(s) != null

有谁知道这是否可能?

4

2 回答 2

2

感谢@HansPassant 的建议,我设法获得了程序集中的字符串文字列表。这与我最初想要的非常接近。

您需要使用读取程序集元数据,并枚举用户字符串。这可以通过以下三种方法来完成IMetaDataImport

[ComImport, Guid("7DAC8207-D3AE-4C75-9B67-92801A497D44")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IMetaDataImport
{
    void CloseEnum(IntPtr hEnum);

    uint GetUserString(uint stk, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] char[] szString, uint cchString, out uint pchString);

    uint EnumUserStrings(ref IntPtr phEnum, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)]uint[] rStrings, uint cmax, out uint pcStrings);

    // interface also contains 62 irrelevant methods
}

要获取 的实例IMetaDataImport,您需要获取IMetaDataDispenser

[ComImport, Guid("809C652E-7396-11D2-9771-00A0C9B4D50C")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[CoClass(typeof(CorMetaDataDispenser))]
interface IMetaDataDispenser
{
    uint OpenScope([MarshalAs(UnmanagedType.LPWStr)]string szScope, uint dwOpenFlags, ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out object ppIUnk);

    // interface also contains 2 irrelevant methods
}

[ComImport, Guid("E5CB7A31-7512-11D2-89CE-0080C792E5D8")]
class CorMetaDataDispenser
{
}

这是怎么回事:

var dispenser = new IMetaDataDispenser();
var metaDataImportGuid = new Guid("7DAC8207-D3AE-4C75-9B67-92801A497D44");

object scope;
var hr = dispenser.OpenScope(location, 0, ref metaDataImportGuid, out scope);

metaDataImport = (IMetaDataImport)scope;    

location程序集文件的路径在哪里。

EnumUserStrings()在那之后,打电话GetUserString()是直截了当的。

这是更详细的博客文章,以及GitHub 上的演示项目

于 2014-03-13T13:05:16.183 回答
1

它指向的SSCLI函数是

STRINGREF*AppDomainStringLiteralMap::GetStringLiteral(EEStringData *pStringData) 
{ 
    ... 
    DWORD dwHash = m_StringToEntryHashTable->GetHash(pStringData);
    if (m_StringToEntryHashTable->GetValue(pStringData, &Data, dwHash))
    {
        STRINGREF *pStrObj = NULL;
        pStrObj = ((StringLiteralEntry*)Data)->GetStringObject();
        _ASSERTE(!bAddIfNotFound || pStrObj);
        return pStrObj;
    }
    else { ... }

    return NULL; //Here, if this returns, the string is not interned
}

如果您设法找到 m_StringToEntryHashTable 的本机地址,则可以枚举存在的字符串。

于 2014-03-06T22:14:14.087 回答