/*
Copyright (C) 2014-2019 de4dot@gmail.com
This file is part of dnSpy
dnSpy is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
dnSpy is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with dnSpy. If not, see .
*/
using System;
using System.Diagnostics;
namespace dnSpy.Debugger.DotNet.Metadata.Impl.COMD {
sealed class DmdPropertyDefCOMD : DmdPropertyDef {
public override string Name { get; }
public override DmdPropertyAttributes Attributes { get; }
readonly DmdComMetadataReader reader;
readonly DmdMethodSignature methodSignature;
public DmdPropertyDefCOMD(DmdComMetadataReader reader, uint rid, DmdType declaringType, DmdType reflectedType) : base(rid, declaringType, reflectedType) {
this.reader = reader ?? throw new ArgumentNullException(nameof(reader));
reader.Dispatcher.VerifyAccess();
uint token = 0x17000000 + rid;
Name = MDAPI.GetPropertyName(reader.MetaDataImport, token) ?? string.Empty;
Attributes = MDAPI.GetPropertyAttributes(reader.MetaDataImport, token);
methodSignature = reader.ReadMethodSignature_COMThread(MDAPI.GetPropertySignatureBlob(reader.MetaDataImport, token), DeclaringType!.GetGenericArguments(), null, isProperty: true);
}
T COMThread(Func action) => reader.Dispatcher.Invoke(action);
public override DmdMethodSignature GetMethodSignature() => methodSignature;
protected override DmdCustomAttributeData[] CreateCustomAttributes() => COMThread(() => reader.ReadCustomAttributesCore_COMThread((uint)MetadataToken));
public override object? GetRawConstantValue() => COMThread(() => reader.ReadPropertyConstant_COMThread(MetadataToken).value);
protected override void GetMethods(out DmdMethodInfo? getMethod, out DmdMethodInfo? setMethod, out DmdMethodInfo[]? otherMethods) {
var info = COMThread(GetMethods_COMThread);
getMethod = info.getMethod;
setMethod = info.setMethod;
otherMethods = info.otherMethods;
}
(DmdMethodInfo? getMethod, DmdMethodInfo? setMethod, DmdMethodInfo[] otherMethods) GetMethods_COMThread() {
reader.Dispatcher.VerifyAccess();
uint token = 0x17000000 + Rid;
MDAPI.GetPropertyGetterSetter(reader.MetaDataImport, token, out uint getToken, out uint setToken);
var otherMethodTokens = MDAPI.GetPropertyOtherMethodTokens(reader.MetaDataImport, token);
var getMethod = Lookup_COMThread(getToken);
var setMethod = Lookup_COMThread(setToken);
var otherMethods = otherMethodTokens.Length == 0 ? Array.Empty() : new DmdMethodInfo[otherMethodTokens.Length];
for (int i = 0; i < otherMethods.Length; i++) {
var otherMethod = Lookup_COMThread(otherMethodTokens[i]);
if (otherMethod is null) {
otherMethods = Array.Empty();
break;
}
otherMethods[i] = otherMethod;
}
return (getMethod, setMethod, otherMethods);
}
DmdMethodInfo? Lookup_COMThread(uint token) {
if ((token >> 24) != 0x06 || (token & 0x00FFFFFF) == 0)
return null;
var method = ReflectedType!.GetMethod(Module, (int)token) as DmdMethodInfo;
Debug2.Assert(method is not null);
return method;
}
}
}