Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Libraries/Opc.Ua.Client.ComplexTypes/ComplexTypeSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -899,7 +899,7 @@ private async Task AddEnumTypesAsync(
if (item is Schema.Binary.EnumeratedType enumeratedObject)
{
// 1. use Dictionary entry
var enumDefinition = enumeratedObject.ToEnumDefinition();
var enumDefinition = enumeratedObject.ToEnumDefinition(enumeratedObject.Name);

// Add EnumDefinition to cache
m_dataTypeDefinitionCache[enumType.NodeId] = enumDefinition;
Expand Down Expand Up @@ -971,12 +971,12 @@ private async Task<Type> AddEnumTypeAsync(
if (enumTypeArray is ExtensionObject[] extensionObject)
{
// 2. use EnumValues
enumDefinition = extensionObject.ToEnumDefinition();
enumDefinition = extensionObject.ToEnumDefinition(name.Name);
}
else if (enumTypeArray is LocalizedText[] localizedText)
{
// 3. use EnumStrings
enumDefinition = localizedText.ToEnumDefinition();
enumDefinition = localizedText.ToEnumDefinition(name.Name);
}
else
{
Expand Down
63 changes: 51 additions & 12 deletions Libraries/Opc.Ua.Client.ComplexTypes/DataTypeDefinitionExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -237,20 +237,33 @@ public static StructureDefinition ToStructureDefinition(
/// Convert a binary schema enumerated type to an enum data type definition
/// Available before OPC UA V1.04.
/// </summary>
public static EnumDefinition ToEnumDefinition(this Schema.Binary.EnumeratedType enumeratedType)
public static EnumDefinition ToEnumDefinition(this Schema.Binary.EnumeratedType enumeratedType, string enumTypeName)
{
var enumDefinition = new EnumDefinition();

foreach (var enumValue in enumeratedType.EnumeratedValue)
if (enumeratedType.EnumeratedValue != null)
{
var enumTypeField = new EnumField
foreach (var enumValue in enumeratedType.EnumeratedValue)
{
Name = enumValue.Name,
Value = enumValue.Value,
Description = enumValue.Documentation?.Text?.FirstOrDefault(),
DisplayName = enumValue.Name
};
enumDefinition.Fields.Add(enumTypeField);
var fieldName = enumValue.Name;
if (string.IsNullOrEmpty(fieldName))
{
if (string.IsNullOrEmpty(enumTypeName))
{
// Here we give up because the overall type is broken
return null;
}
fieldName = $"{enumTypeName}_{enumValue.Value}";
}

var enumTypeField = new EnumField {
Name = fieldName,
Value = enumValue.Value,
Description = enumValue.Documentation?.Text?.FirstOrDefault(),
DisplayName = enumValue.Name
};
enumDefinition.Fields.Add(enumTypeField);
}
}

return enumDefinition;
Expand All @@ -260,14 +273,30 @@ public static EnumDefinition ToEnumDefinition(this Schema.Binary.EnumeratedType
/// Convert a list of EnumValues to an enum data type definition
/// Available before OPC UA V1.04.
/// </summary>
public static EnumDefinition ToEnumDefinition(this ExtensionObject[] enumValueTypes)
public static EnumDefinition ToEnumDefinition(this ExtensionObject[] enumValueTypes, string enumTypeName)
{
var enumDefinition = new EnumDefinition();

foreach (var extensionObject in enumValueTypes)
{
var enumValue = extensionObject.Body as EnumValueType;
if (extensionObject.Body is not EnumValueType enumValue)
{
// All we can do here is skip this value. Since there is no
// fallback it is better to include all other type fields if
// they are in the extension object array.
continue;
}

var name = enumValue.DisplayName.Text;
if (string.IsNullOrEmpty(name))
{
if (string.IsNullOrEmpty(enumTypeName))
{
// Here we give up because the overall type is broken
return null;
}
name = $"{enumTypeName}_{enumValue.Value}";
}

var enumTypeField = new EnumField {
Name = name,
Expand All @@ -284,7 +313,7 @@ public static EnumDefinition ToEnumDefinition(this ExtensionObject[] enumValueTy
/// Convert a list of EnumValues to an enum data type definition
/// Available before OPC UA V1.04.
/// </summary>
public static EnumDefinition ToEnumDefinition(this LocalizedText[] enumFieldNames)
public static EnumDefinition ToEnumDefinition(this LocalizedText[] enumFieldNames, string enumTypeName)
{
var enumDefinition = new EnumDefinition();

Expand All @@ -293,6 +322,16 @@ public static EnumDefinition ToEnumDefinition(this LocalizedText[] enumFieldName
LocalizedText enumFieldName = enumFieldNames[ii];
var name = enumFieldName.Text;

if (string.IsNullOrEmpty(name))
{
if (string.IsNullOrEmpty(enumTypeName))
{
// Here we give up because the overall type is broken
return null;
}
name = $"{enumTypeName}_{ii}";
}

var enumTypeField = new EnumField {
Name = name,
Value = ii,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
* ======================================================================*/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
Expand Down Expand Up @@ -79,16 +80,42 @@ public Type AddEnumType(QualifiedName typeName, EnumDefinition enumDefinition)
{
throw new ArgumentNullException(nameof(enumDefinition));
}
if (typeName == null)
{
throw new ArgumentNullException(nameof(typeName));
}

if (string.IsNullOrEmpty(typeName.Name))
{
// The type name should not be null or empty then the type definition
// or xml is broken. For the latter we want to go into the fallback path
// And try to read the data type definition's enum definition.
return null;
}

var enumBuilder = m_moduleBuilder.DefineEnum(
GetFullQualifiedTypeName(typeName),
TypeAttributes.Public,
typeof(int));
enumBuilder.DataContractAttribute(m_targetNamespace);
foreach (var enumValue in enumDefinition.Fields)
if (enumDefinition.Fields != null)
{
var newEnum = enumBuilder.DefineLiteral(enumValue.Name, (int)enumValue.Value);
newEnum.EnumMemberAttribute(enumValue.Name, (int)enumValue.Value);
var fieldNames = new HashSet<string>();
foreach (EnumField enumValue in enumDefinition.Fields)
{
// Create a field from the type name and ensure it is not a duplicate
var fieldName = enumValue.Name;
if (string.IsNullOrEmpty(fieldName))
{
// This is to be super safe, but we should never get here.
fieldName = $"{typeName.Name}_{enumValue.Value}";
}
if (fieldNames.Add(fieldName))
{
var newEnum = enumBuilder.DefineLiteral(fieldName, (int)enumValue.Value);
newEnum.EnumMemberAttribute(fieldName, (int)enumValue.Value);
}
}
}
return enumBuilder.CreateTypeInfo();
}
Expand Down
Loading