如何用Delphi的.NET Runtime Library读取Assembly DLL的AssemblyID及解决相关问题
获取程序集Assembly ID(GUID)的问题与解决方法
问题描述
- 需求:创建函数直接从Assembly DLL读取AssemblyID,用于通用注册程序集,调用方式为:
TClrAssembly.RegisterDLLAssembly(AssemblyGuid, AssemblyLocation, ltfileLocation); - 当前方案问题:部分DLL的CustomAttributesData列表中缺少GuidAttribute,部分存在该属性但内容与预期GUID不符。
- 当前代码:
function GUIDFromAssembly(AssemblyFileName: string): string; var InspectedAssembly: _Assembly; GenericList: _GenericIList; GenericItems: _GenericICollection; begin result := ''; InspectedAssembly:= CoAssemblyHelper.CreateInstance.ReflectionOnlyLoadFrom(AssemblyFileName); if not assigned(InspectedAssembly) then raise Exception.CreateFmt('Assembly %s not found', [AssemblyFileName]); GenericList := InspectedAssembly.GetCustomAttributesData; GenericItems := GenericList.AsGenericICollection; for c := 0 to GenericItems.Count - 1 do begin s := GenericList.Item[c].ToString; Log(c.ToString + ': ' + s); if s.StartsWith('[System.Runtime.InteropServices.GuidAttribute("') then result := s.Substring(47, 36); end; end; - 额外疑问:_GenericIList为何没有Length属性?通过AsGenericICollection遍历的方式是否正确?
解决方案
正确获取Assembly GUID的方式
你当前通过解析CustomAttributesData字符串的方式不可靠,原因有两点:一是并非所有程序集都会显式标记GuidAttribute;二是字符串解析容易因格式变动出错。
推荐两种更可靠的实现方式:
方式1:直接读取程序集的Guid属性
function GUIDFromAssembly(AssemblyFileName: string): string; var InspectedAssembly: _Assembly; GuidValue: TGUID; begin Result := ''; InspectedAssembly := CoAssemblyHelper.CreateInstance.ReflectionOnlyLoadFrom(AssemblyFileName); if not Assigned(InspectedAssembly) then raise Exception.CreateFmt('Assembly %s not found', [AssemblyFileName]); // 直接获取程序集内置的Guid if Succeeded(InspectedAssembly.GetGuid(GuidValue)) then Result := GUIDToString(GuidValue); end;
方式2:通过AssemblyName获取
如果方式1无法使用,可通过程序集名称对象读取Guid:
function GUIDFromAssembly(AssemblyFileName: string): string; var AssemblyName: _AssemblyName; GuidValue: TGUID; begin Result := ''; AssemblyName := CoAssemblyName.CreateInstance; AssemblyName.InitFromFile(AssemblyFileName); if Succeeded(AssemblyName.GetGuid(GuidValue)) then Result := GUIDToString(GuidValue); end;
关于_GenericIList的疑问解答
- 为何没有Length属性:.NET原生的
IList<T>接口定义的是Count属性而非Length,Length一般用于数组类型。你使用的_GenericIList是COM互操作映射后的接口,遵循原.NET接口规范,因此只有Count属性。 - AsGenericICollection遍历是否正确:这种方式可行,但没必要——直接利用
_GenericIList自身的Count属性遍历更高效,无需转换为_GenericICollection:
转换为GenericList := InspectedAssembly.GetCustomAttributesData; for c := 0 to GenericList.Count - 1 do begin // 处理逻辑 end;_GenericICollection主要是为了使用ICollection接口的Add、Remove等修改类方法,单纯遍历的话直接用_GenericIList即可。
内容的提问来源于stack exchange,提问作者user20518651
相关产品推荐
相关产品推荐

