diff --git a/src/dscom.test/builder/DynamicMethodBuilder.cs b/src/dscom.test/builder/DynamicMethodBuilder.cs index 42dd63fe..5f2e315b 100644 --- a/src/dscom.test/builder/DynamicMethodBuilder.cs +++ b/src/dscom.test/builder/DynamicMethodBuilder.cs @@ -16,16 +16,6 @@ namespace dSPACE.Runtime.InteropServices.Tests; internal sealed class DynamicMethodBuilder : DynamicBuilder { - internal record struct DefaultValue( - object? Value - ); - - internal record struct ParameterItem( - Type Type, - ParameterAttributes? ParameterAttributes, - DefaultValue? DefaultValue = null - ); - public DynamicMethodBuilder(DynamicTypeBuilder dynamicTypeBuilder, string name) : base(name) { DynamicTypeBuilder = dynamicTypeBuilder; @@ -37,14 +27,10 @@ public DynamicMethodBuilder(DynamicTypeBuilder dynamicTypeBuilder, string name) private Tuple? ReturnTypeAttribute { get; set; } - public List ParamterItems { get; } = new(); - - public Tuple[]? ParamAttributes { get; set; } - - public Dictionary> ParamAttributesFieldValues { get; set; } = new(); - protected override AttributeTargets AttributeTarget => AttributeTargets.Method; + private readonly DynamicParameterBuilder _parameterBuilder = new(); + public DynamicMethodBuilder WithReturnType(Type type) { ReturnType = type; @@ -64,13 +50,13 @@ public DynamicMethodBuilder WithParameter() public DynamicMethodBuilder WithParameter(Type parameterType) { - ParamterItems.Add(new ParameterItem(parameterType, null)); + _parameterBuilder.AddParameter(new ParameterItem(parameterType, null)); return this; } public DynamicMethodBuilder WithParameter(ParameterItem parameterItem) { - ParamterItems.Add(parameterItem); + _parameterBuilder.AddParameter(parameterItem); return this; } @@ -82,26 +68,19 @@ public DynamicMethodBuilder WithReturnTypeCustomAttribute(object value) public DynamicMethodBuilder WithParameterCustomAttribute(int parameterIndex) { - var attributes = ParamAttributes ?? new Tuple[ParamterItems == null ? 0 : ParamterItems.Count]; - attributes[parameterIndex] = new(typeof(T), null); - ParamAttributes = attributes; - return this; + return WithParameterCustomAttribute(parameterIndex, null); } - public DynamicMethodBuilder WithParameterCustomAttribute(int parameterIndex, object value) + public DynamicMethodBuilder WithParameterCustomAttribute(int parameterIndex, object? value) { - var attributes = ParamAttributes ?? new Tuple[ParamterItems == null ? 0 : ParamterItems.Count]; - attributes[parameterIndex] = new(typeof(T), value); - ParamAttributes = attributes; + _parameterBuilder.AddParameterAttribute(parameterIndex, value); return this; } public DynamicMethodBuilder WithParameterCustomAttribute(int parameterIndex, object value, FieldInfo[] namedFields, object?[] fieldValues) { - var attributes = ParamAttributes ?? new Tuple[ParamterItems == null ? 0 : ParamterItems.Count]; - attributes[parameterIndex] = new(typeof(T), value); - ParamAttributes = attributes; - ParamAttributesFieldValues[parameterIndex] = new(namedFields, fieldValues); + _parameterBuilder.AddParameterAttribute(parameterIndex, value); + _parameterBuilder.AddParameterCustomAttributeFieldValue(parameterIndex, namedFields, fieldValues); return this; } @@ -109,7 +88,7 @@ public DynamicTypeBuilder CreateMethod() { var methodBuilder = DynamicTypeBuilder.TypeBuilder!.DefineMethod(Name, MethodAttributes.Abstract | MethodAttributes.Public | MethodAttributes.Virtual, - CallingConventions.HasThis, ReturnType, ParamterItems.Select(p => p.Type).ToArray()); + CallingConventions.HasThis, ReturnType, _parameterBuilder.GetParameterTypes()); var returnParamBuilder = methodBuilder.DefineParameter(0, ParameterAttributes.Retval, null); if (ReturnTypeAttribute != null) @@ -123,43 +102,7 @@ public DynamicTypeBuilder CreateMethod() returnParamBuilder.SetCustomAttribute(attributeBuilder); } - var index = 1; - - foreach (var item in ParamterItems) - { - var hasDefaultValue = item.DefaultValue != null; - - var parameterAttribute = item.ParameterAttributes; - parameterAttribute ??= hasDefaultValue ? ParameterAttributes.HasDefault : ParameterAttributes.None; - - var paramBuilder = methodBuilder.DefineParameter(index, parameterAttribute.Value, $"Param{index}"); - if (ParamAttributes != null) - { - //use parameter attributes - if ((ParamAttributes.Length > index - 1) && ParamAttributes.GetValue(index - 1) != null) - { - var attributeParam = ParamAttributes[index - 1].Item2; - var typeAttributeParam = ParamAttributes[index - 1].Item2 == null ? typeof(object) : ParamAttributes[index - 1].Item2?.GetType(); - var typeAttribute = ParamAttributes[index - 1].Item1; - - var attributeConstructor = attributeParam != null && typeAttributeParam != null ? typeAttribute.GetConstructor(new Type[] { typeAttributeParam }) : typeAttribute.GetConstructor(Array.Empty()); - - ParamAttributesFieldValues.TryGetValue(index - 1, out var fields); - - var attributeBuilder = attributeParam == null - ? new CustomAttributeBuilder(attributeConstructor!, Array.Empty()) - : fields != null - ? new CustomAttributeBuilder(attributeConstructor!, new object[] { attributeParam }, fields.Item1, fields.Item2) - : new CustomAttributeBuilder(attributeConstructor!, new object[] { attributeParam }); - paramBuilder.SetCustomAttribute(attributeBuilder); - } - } - if (hasDefaultValue) - { - paramBuilder.SetConstant(item.DefaultValue!.Value.Value); - } - index++; - } + _parameterBuilder.AddParameters(methodBuilder); foreach (var customAttributeBuilder in CustomAttributeBuilder) { diff --git a/src/dscom.test/builder/DynamicParameterBuilder.cs b/src/dscom.test/builder/DynamicParameterBuilder.cs new file mode 100644 index 00000000..f8c0af13 --- /dev/null +++ b/src/dscom.test/builder/DynamicParameterBuilder.cs @@ -0,0 +1,99 @@ +// Copyright 2022 dSPACE GmbH, Mark Lechtermann, Matthias Nissen and Contributors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +namespace dSPACE.Runtime.InteropServices.Tests; + +internal record struct DefaultValue( + object? Value + ); + +internal record struct ParameterItem( + Type Type, + ParameterAttributes? ParameterAttributes, + DefaultValue? DefaultValue = null + ); + +internal sealed class DynamicParameterBuilder +{ + public int Count => _parameterItems.Count; + + private readonly List _parameterItems = new(); + + private Tuple[]? _paramAttributes; + + private readonly Dictionary> _paramAttributesFieldValues = new(); + + public void AddParameterAttribute(int parameterIndex, object? value) + { + var attributes = _paramAttributes ?? new Tuple[_parameterItems == null ? 0 : _parameterItems.Count]; + attributes[parameterIndex] = new(typeof(T), value); + _paramAttributes = attributes; + } + + public void AddParameterCustomAttributeFieldValue(int parameterIndex, FieldInfo[] namedFields, object?[] fieldValues) + { + _paramAttributesFieldValues[parameterIndex] = new(namedFields, fieldValues); + } + + public Type[] GetParameterTypes() + { + return _parameterItems.Select(p => p.Type).ToArray(); + } + public void AddParameter(ParameterItem parameter) + { + _parameterItems.Add(parameter); + } + + public void AddParameters(MethodBuilder methodBuilder, int index = 1) + { + for (var iParameter = 0; iParameter < _parameterItems.Count; iParameter++) + { + var item = _parameterItems[iParameter]; + + var hasDefaultValue = item.DefaultValue != null; + + var parameterAttribute = item.ParameterAttributes; + parameterAttribute ??= hasDefaultValue ? ParameterAttributes.HasDefault : ParameterAttributes.None; + + var paramBuilder = methodBuilder.DefineParameter(index, parameterAttribute.Value, $"Param{index}"); + if (_paramAttributes != null) + { + //use parameter attributes + if ((_paramAttributes.Length > iParameter) && _paramAttributes.GetValue(iParameter) != null) + { + var attributeParam = _paramAttributes[iParameter].Item2; + var typeAttributeParam = _paramAttributes[iParameter].Item2 == null ? typeof(object) : _paramAttributes[iParameter].Item2?.GetType(); + var typeAttribute = _paramAttributes[iParameter].Item1; + + var attributeConstructor = attributeParam != null && typeAttributeParam != null ? typeAttribute.GetConstructor(new Type[] { typeAttributeParam }) : typeAttribute.GetConstructor(Array.Empty()); + + _paramAttributesFieldValues.TryGetValue(iParameter, out var fields); + + var attributeBuilder = attributeParam == null + ? new CustomAttributeBuilder(attributeConstructor!, Array.Empty()) + : fields != null + ? new CustomAttributeBuilder(attributeConstructor!, new object[] { attributeParam }, fields.Item1, fields.Item2) + : new CustomAttributeBuilder(attributeConstructor!, new object[] { attributeParam }); + paramBuilder.SetCustomAttribute(attributeBuilder); + } + } + if (hasDefaultValue) + { + paramBuilder.SetConstant(item.DefaultValue!.Value.Value); + } + + index++; + } + } +} diff --git a/src/dscom.test/builder/DynamicPropertyBuilder.cs b/src/dscom.test/builder/DynamicPropertyBuilder.cs index d97d94b8..875c494e 100644 --- a/src/dscom.test/builder/DynamicPropertyBuilder.cs +++ b/src/dscom.test/builder/DynamicPropertyBuilder.cs @@ -18,79 +18,99 @@ internal sealed class DynamicPropertyBuilder : DynamicBuilder? ReturnTypeCustomAttributes { get; private set; } + private readonly DynamicTypeBuilder _dynamicTypeBuilder; + + private Tuple? _returnTypeCustomAttributes; - public Tuple? ParameterCustomAttributes { get; private set; } + private Tuple? _parameterCustomAttributes; protected override AttributeTargets AttributeTarget => AttributeTargets.Property; + private readonly DynamicParameterBuilder _indexParameterBuilder = new(); + + private static readonly MethodAttributes _methodAttributes = + MethodAttributes.Public + | MethodAttributes.SpecialName + | MethodAttributes.HideBySig + | MethodAttributes.Abstract + | MethodAttributes.Virtual; + public DynamicTypeBuilder CreateProperty() { - var propertyBuilder = DynamicTypeBuilder.TypeBuilder!.DefineProperty(Name, PropertyAttributes.None, CallingConventions.HasThis, PropertyType, null); + var propertyBuilder = _dynamicTypeBuilder.TypeBuilder!.DefineProperty(Name, PropertyAttributes.None, CallingConventions.HasThis, PropertyType, null); if (IsGettable) { var specialName = $"get_{Name}"; - var getterMethdoBuilder = DynamicTypeBuilder.TypeBuilder.DefineMethod(specialName, - MethodAttributes.Public | MethodAttributes.SpecialName | - MethodAttributes.HideBySig | MethodAttributes.Abstract | MethodAttributes.Virtual, + var getterMethodBuilder = _dynamicTypeBuilder.TypeBuilder.DefineMethod( + specialName, + _methodAttributes, CallingConventions.HasThis, - PropertyType, null); + PropertyType, + _indexParameterBuilder.GetParameterTypes()); + + _indexParameterBuilder.AddParameters(getterMethodBuilder, 0); - if (ReturnTypeCustomAttributes != null) + if (_returnTypeCustomAttributes != null) { - var attributeParam = ReturnTypeCustomAttributes.Item2; - var typeAttributeParam = ReturnTypeCustomAttributes.Item2.GetType(); - var typeAttribute = ReturnTypeCustomAttributes.Item1; + var attributeParam = _returnTypeCustomAttributes.Item2; + var typeAttributeParam = _returnTypeCustomAttributes.Item2.GetType(); + var typeAttribute = _returnTypeCustomAttributes.Item1; var attributeConstructor = typeAttribute.GetConstructor(new Type[] { typeAttributeParam }); var attributeBuilder = new CustomAttributeBuilder(attributeConstructor!, new object[] { attributeParam }); var returnValueParameterBuilder = - getterMethdoBuilder.DefineParameter(0, ParameterAttributes.Retval, null); - + getterMethodBuilder.DefineParameter(_indexParameterBuilder.Count, ParameterAttributes.Retval, null); returnValueParameterBuilder.SetCustomAttribute(attributeBuilder); } - propertyBuilder.SetGetMethod(getterMethdoBuilder); + propertyBuilder.SetGetMethod(getterMethodBuilder); } + if (IsSettable) { + var parameterTypes = Enumerable + .Repeat(PropertyType, 1) + .Concat(_indexParameterBuilder.GetParameterTypes()) + .ToArray(); + var specialName = $"set_{Name}"; - var setterMethdoBuilder = DynamicTypeBuilder.TypeBuilder.DefineMethod(specialName, - MethodAttributes.Public | MethodAttributes.SpecialName | - MethodAttributes.HideBySig | MethodAttributes.Abstract | MethodAttributes.Virtual, + var setterMethodBuilder = _dynamicTypeBuilder.TypeBuilder.DefineMethod( + specialName, + _methodAttributes, CallingConventions.HasThis, - null, new Type[] { PropertyType }); + null, + parameterTypes); + + _indexParameterBuilder.AddParameters(setterMethodBuilder, 1); - if (ParameterCustomAttributes != null) + if (_parameterCustomAttributes != null) { - var attributeParam = ParameterCustomAttributes.Item2; - var typeAttributeParam = ParameterCustomAttributes.Item2.GetType(); - var typeAttribute = ParameterCustomAttributes.Item1; + var attributeParam = _parameterCustomAttributes.Item2; + var typeAttributeParam = _parameterCustomAttributes.Item2.GetType(); + var typeAttribute = _parameterCustomAttributes.Item1; var attributeConstructor = typeAttribute.GetConstructor(new Type[] { typeAttributeParam }); var attributeBuilder = new CustomAttributeBuilder(attributeConstructor!, new object[] { attributeParam }); var returnValueParameterBuilder = - setterMethdoBuilder.DefineParameter(1, ParameterAttributes.HasFieldMarshal, null); + setterMethodBuilder.DefineParameter(1, ParameterAttributes.HasFieldMarshal, null); returnValueParameterBuilder.SetCustomAttribute(attributeBuilder); } - propertyBuilder.SetSetMethod(setterMethdoBuilder); + propertyBuilder.SetSetMethod(setterMethodBuilder); } foreach (var customAttributeBuilder in CustomAttributeBuilder) @@ -98,25 +118,40 @@ public DynamicTypeBuilder CreateProperty() propertyBuilder.SetCustomAttribute(customAttributeBuilder); } - return DynamicTypeBuilder; + return _dynamicTypeBuilder; } - public DynamicPropertyBuilder WithReturnTypeCustomAttribute(object value) { - ReturnTypeCustomAttributes = new Tuple(typeof(T), value); + _returnTypeCustomAttributes = new Tuple(typeof(T), value); return this; - } public DynamicPropertyBuilder WithParameterCustomAttribute(object value) + where T : Attribute + { + _parameterCustomAttributes = new Tuple(typeof(T), value); + return this; + } + + public DynamicPropertyBuilder WithIndexParameter() + { + return WithIndexParameter(typeof(T)); + } + + public DynamicPropertyBuilder WithIndexParameter(Type parameterType) + { + return WithIndexParameter(new ParameterItem(parameterType, null)); + } + + public DynamicPropertyBuilder WithIndexParameter(ParameterItem parameterItem) { - ParameterCustomAttributes = new Tuple(typeof(T), value); + _indexParameterBuilder?.AddParameter(parameterItem); return this; } public DynamicTypeBuilder Build() { - return DynamicTypeBuilder; + return _dynamicTypeBuilder; } } diff --git a/src/dscom.test/tests/MemIdTest.cs b/src/dscom.test/tests/MemIdTest.cs index 2534d2f0..44b9cedd 100644 --- a/src/dscom.test/tests/MemIdTest.cs +++ b/src/dscom.test/tests/MemIdTest.cs @@ -202,6 +202,23 @@ public void ValuePropertyWithDispIdAttributeValue123_DispId123IsUsed() func!.Value.memid.Should().Be(123); } + [Fact] + public void ValueProperty_DispId0IsNotUsed() + { + var result = CreateAssembly() + .WithInterface("TestInterface") + .WithProperty("Value", typeof(string)) + .WithIndexParameter(typeof(string)) + .Build() + .Build() + .Build(); + + using var func = result!.TypeLib.GetTypeInfoByName("TestInterface")!.GetFuncDescByName("Value"); + func.Should().NotBeNull("Value property should be available"); + + func!.Value.memid.Should().NotBe(0); + } + [Fact] public void ItemMethodWithDispIdAttributeValue123_DispId123IsUsed() { diff --git a/src/dscom.test/tests/MethodTests.cs b/src/dscom.test/tests/MethodTests.cs index c9efb425..516b5c20 100644 --- a/src/dscom.test/tests/MethodTests.cs +++ b/src/dscom.test/tests/MethodTests.cs @@ -314,7 +314,7 @@ public void MethodWithParameterWithDefaultValue_HasDefaultValue(Type parameterTy .WithInterface("TestInterface").WithCustomAttribute(ComInterfaceType.InterfaceIsIDispatch) .WithMethod("TestMethod") .WithReturnType(typeof(void)) - .WithParameter(new DynamicMethodBuilder.ParameterItem { Type = parameterType, ParameterAttributes = ParameterAttributes.Optional | ParameterAttributes.HasDefault, DefaultValue = new DynamicMethodBuilder.DefaultValue(value) }) + .WithParameter(new ParameterItem { Type = parameterType, ParameterAttributes = ParameterAttributes.Optional | ParameterAttributes.HasDefault, DefaultValue = new DefaultValue(value) }) .Build() .Build() .Build(); @@ -949,7 +949,7 @@ public void InterfaceIsIUnknownWithMethodWithOutParameter_OutParameterIsCorrect( .WithInterface("TestInterface") .WithCustomAttribute(ComInterfaceType.InterfaceIsIUnknown) .WithMethod("TestMethod") - .WithParameter(new DynamicMethodBuilder.ParameterItem { Type = parameterType, ParameterAttributes = ParameterAttributes.Out }) + .WithParameter(new ParameterItem { Type = parameterType, ParameterAttributes = ParameterAttributes.Out }) .Build() .Build() .Build(); @@ -1010,7 +1010,7 @@ public void InterfaceIsIDispatchWithMethodWithOutParameter_OutParameterIsCorrect .WithInterface("TestInterface") .WithCustomAttribute(ComInterfaceType.InterfaceIsIDispatch) .WithMethod("TestMethod") - .WithParameter(new DynamicMethodBuilder.ParameterItem { Type = parameterType, ParameterAttributes = ParameterAttributes.Out }) + .WithParameter(new ParameterItem { Type = parameterType, ParameterAttributes = ParameterAttributes.Out }) .Build() .Build() .Build(); @@ -1071,7 +1071,7 @@ public void InterfaceIsDualWithMethodWithOutParameter_OutParameterIsCorrect(Type .WithInterface("TestInterface") .WithCustomAttribute(ComInterfaceType.InterfaceIsDual) .WithMethod("TestMethod") - .WithParameter(new DynamicMethodBuilder.ParameterItem { Type = parameterType, ParameterAttributes = ParameterAttributes.Out }) + .WithParameter(new ParameterItem { Type = parameterType, ParameterAttributes = ParameterAttributes.Out }) .Build() .Build() .Build(); @@ -1130,7 +1130,7 @@ public void InterfaceIsIUnknownWithMethodWithArrayOutParameter_OutParameterIsCor .WithInterface("TestInterface") .WithCustomAttribute(ComInterfaceType.InterfaceIsIUnknown) .WithMethod("TestMethod") - .WithParameter(new DynamicMethodBuilder.ParameterItem { Type = parameterType.MakeArrayType(), ParameterAttributes = ParameterAttributes.Out }) + .WithParameter(new ParameterItem { Type = parameterType.MakeArrayType(), ParameterAttributes = ParameterAttributes.Out }) .Build() .Build() .Build(); @@ -1182,7 +1182,7 @@ public void InterfaceIsIDispatchWithMethodWithArrayOutParameter_OutParameterIsCo .WithInterface("TestInterface") .WithCustomAttribute(ComInterfaceType.InterfaceIsIDispatch) .WithMethod("TestMethod") - .WithParameter(new DynamicMethodBuilder.ParameterItem { Type = parameterType.MakeArrayType(), ParameterAttributes = ParameterAttributes.Out }) + .WithParameter(new ParameterItem { Type = parameterType.MakeArrayType(), ParameterAttributes = ParameterAttributes.Out }) .Build() .Build() .Build(); @@ -1234,7 +1234,7 @@ public void InterfaceIsDualWithMethodWithArrayOutParameter_OutParameterIsCorrect .WithInterface("TestInterface") .WithCustomAttribute(ComInterfaceType.InterfaceIsDual) .WithMethod("TestMethod") - .WithParameter(new DynamicMethodBuilder.ParameterItem { Type = parameterType.MakeArrayType(), ParameterAttributes = ParameterAttributes.Out }) + .WithParameter(new ParameterItem { Type = parameterType.MakeArrayType(), ParameterAttributes = ParameterAttributes.Out }) .Build() .Build() .Build(); @@ -1272,7 +1272,7 @@ public void InterfaceWithMethodWithArrayOutParameteMakeByRefTypeOfUserDefine_Out .WithInterface("TestInterface") .WithCustomAttribute(comInterfaceType) .WithMethod("TestMethod") - .WithParameter(new DynamicMethodBuilder.ParameterItem { Type = customInterface!.MakeArrayType().MakeByRefType(), ParameterAttributes = ParameterAttributes.Out }) + .WithParameter(new ParameterItem { Type = customInterface!.MakeArrayType().MakeByRefType(), ParameterAttributes = ParameterAttributes.Out }) .Build() .Build() .Build(); @@ -1367,10 +1367,10 @@ public void MethodWithOptionalObjectArrayParameter_MethodIsAvailable() .WithInterface("CustomInterface").Build(out var customInterface) .WithInterface("TestInterface") .WithMethod("TestMethod") - .WithParameter(new DynamicMethodBuilder.ParameterItem() + .WithParameter(new ParameterItem() { ParameterAttributes = ParameterAttributes.Optional | ParameterAttributes.HasDefault, - DefaultValue = new DynamicMethodBuilder.DefaultValue() { Value = null }, + DefaultValue = new DefaultValue() { Value = null }, Type = customInterface!.MakeArrayType(), }) .Build() @@ -1425,10 +1425,10 @@ public void MethodWithDefaultParameterValueAttribute_DefaultValueIsUsed(Type par var result = CreateAssembly(new AssemblyName($"Dynamic{parameterType}{defaultValue}")) .WithInterface("TestInterface") .WithMethod("TestMethod") - .WithParameter(new DynamicMethodBuilder.ParameterItem() + .WithParameter(new ParameterItem() { ParameterAttributes = ParameterAttributes.HasDefault, - DefaultValue = new DynamicMethodBuilder.DefaultValue() { Value = Convert.ChangeType(defaultValue, parameterType) }, + DefaultValue = new DefaultValue() { Value = Convert.ChangeType(defaultValue, parameterType) }, Type = parameterType, }) .Build() diff --git a/src/dscom.test/tests/NamesTest.cs b/src/dscom.test/tests/NamesTest.cs index 424dc6be..e5608da8 100644 --- a/src/dscom.test/tests/NamesTest.cs +++ b/src/dscom.test/tests/NamesTest.cs @@ -14,7 +14,6 @@ using System.Runtime.InteropServices; using dSPACE.Runtime.InteropServices.Attributes; -using static dSPACE.Runtime.InteropServices.Tests.DynamicMethodBuilder; namespace dSPACE.Runtime.InteropServices.Tests; diff --git a/src/dscom/DispatchIdCreator.cs b/src/dscom/DispatchIdCreator.cs index db04a1fb..e1afb503 100644 --- a/src/dscom/DispatchIdCreator.cs +++ b/src/dscom/DispatchIdCreator.cs @@ -110,7 +110,7 @@ internal void NormalizeIds() } // If DispId == 0 not used by any member, Value should take the 0 (if the DispId for the Value property is not explicit defined). - var valueItem = _dispIds.FirstOrDefault(z => z.MemberInfo.Name.Equals("Value", StringComparison.Ordinal)); + var valueItem = _dispIds.FirstOrDefault(z => IsDefaultMemberInfo(z.MemberInfo)); if (valueItem != null) { if (!_dispIds.Any(i => i.Id == 0) && !valueItem.ExplicitId.HasValue) @@ -120,6 +120,29 @@ internal void NormalizeIds() } } + private static bool IsDefaultMemberInfo(MemberInfo memberInfo) + { + // Only Member with name 'value' are set to DispId(0) by default + if (!memberInfo.Name.Equals("Value", StringComparison.Ordinal)) + { + return false; + } + + // Only Properties are considered + if (memberInfo is not PropertyInfo propertyInfo) + { + return false; + } + + // Only Properties without a parameter + if (propertyInfo.GetIndexParameters().Length > 0) + { + return false; + } + + return true; + } + public sealed class IDInfo { public IDInfo(uint generatedId, uint? explicitId, MemberInfo memberInfo)