Tpm2Lib.TpmStructureBase.GetFieldsToMarshal C# (CSharp) Method

GetFieldsToMarshal() private method

private GetFieldsToMarshal ( bool trackTags = false ) : TpmStructMemberInfo[]
trackTags bool
return TpmStructMemberInfo[]
        TpmStructMemberInfo[] GetFieldsToMarshal(bool trackTags = false)
        {
            var t = GetType();
            string caption = (trackTags ? "Unmarshaling" : "Marshaling") + " " + t.Name;
            if (!t.GetTypeInfo().IsValueType)
            {
                var b = t.GetTypeInfo().BaseType;
                if (b != null && b != typeof(TpmStructureBase) && b != typeof(object))
                {
                    t = b;
                    caption += " as " + b.Name;
                }
            }
            dbg.Trace(caption);
            dbg.Indent();
            var members = new SortedDictionary<int, TpmStructMemberInfo>();
            Dictionary<string, TpmStructMemberInfo> tags = null;
            //Dictionary<string, TpmStructMemberInfo> untaggedFields = null;
            if (trackTags)
            {
                tags = new Dictionary<string, TpmStructMemberInfo>();
                //untaggedFields = new Dictionary<string, TpmStructMemberInfo>();
            }
            foreach (var bf in new BindingFlags[] {BindingFlags.Public | BindingFlags.NonPublic})
            {
                var candidateMembers = t.GetMembers(BindingFlags.Instance | bf);
                foreach (var mi in candidateMembers)
                {
                    var memberAttrs = mi.CustomAttributes;
                    foreach (var a in memberAttrs)
                    {
                        if (a.AttributeType.Name != "MarshalAsAttribute")
                        {
                            continue;
                        }
                        int idx = 0;
                        var arg0 = a.ConstructorArguments[0];
                        if (arg0.ArgumentType == typeof(int))
                        {
                            idx = (int)arg0.Value;
                        }
                        else
                        {
                            // The only variant of the marshaling attribute with
                            // a non-int first argument:
                            //     arg0.ArgumentType == typeof(Type))
                            // is used for types only, and never for structure fields.
                            Debug.Assert(false);
                        }

                        members.Add(idx, mi);

                        var tsmi = members[idx];
                        var arg1 = a.ConstructorArguments[1];
                        Debug.Assert(arg1.ArgumentType == typeof(MarshalType));
                        var mt = (MarshalType)arg1.Value;
                        Debug.Assert(mt != MarshalType.ArrayCount && mt != MarshalType.LengthOfStruct);

                        tsmi.WireType = mt;
                        if (mt == MarshalType.VariableLengthArray || mt == MarshalType.SizedStruct)
                        {
                            tsmi.SizeName = (string)a.ConstructorArguments[2].Value;
                            tsmi.SizeLength = (int)a.ConstructorArguments[3].Value;
                            dbg.Trace("Preproc " + (mt == MarshalType.SizedStruct ? "Struct " : "Array ")
                                      + mi.Name + " with size tag " + tsmi.SizeName + "=" + tsmi.SizeLength);
                        }

                        if (trackTags)
                        {
                            var marshalType = (MarshalType)arg1.Value;
                            switch (marshalType)
                            {
                                case MarshalType.UnionSelector:
                                {
                                    tags.Add(mi.Name, tsmi);
                                    dbg.Trace("Preproc Selector: " + mi.Name);
                                    break;
                                }
                                case MarshalType.Union:
                                {
                                    var selector = a.ConstructorArguments[2].Value;
                                    dbg.Trace("Preproc Union " + mi.Name + " with selector " + selector);
                                    tsmi.Tag = tags[(string)selector];
                                    break;
                                }
#if false
                                case MarshalType.ArrayCount:
                                {
                                    tags.Add(mi.Name, tsmi);
                                    dbg.Trace("Preproc Array Count: " + mi.Name);
                                    break;
                                }
                                case MarshalType.VariableLengthArray:
                                {
                                    var sizeTag = a.ConstructorArguments[2].Value;
                                    dbg.Trace("Preproc Array " + mi.Name + " with size tag " + sizeTag);
                                    tsmi.Tag = tags[(string)sizeTag];
                                    break;
                                }
                                case MarshalType.LengthOfStruct:
                                {
                                    var sizedStruct = (string)a.ConstructorArguments[2].Value;
                                    dbg.Trace("Preproc Size Tag " + mi.Name + " for struct " + sizedStruct);
                                    if (untaggedFields.ContainsKey(sizedStruct))
                                    {
                                        untaggedFields[sizedStruct].Tag = tsmi;
                                    }
                                    else
                                    {
                                        tags.Add(sizedStruct, tsmi);
                                    }
                                    break;
                                }
                                default:
                                {
                                    // Check if this is a sized struct
                                    if (tags.ContainsKey(mi.Name))
                                    {
                                        tsmi.Tag = tags[mi.Name];
                                        dbg.Trace("Preproc Sized Struct" + mi.Name + " with size tag " + tsmi.Tag.Name);
                                    }
                                    else
                                    {
                                        untaggedFields.Add(mi.Name, tsmi);
                                    }
                                    break;
                                }
#endif
                            }
                        }
                        break;
                    }
                }
            }
            dbg.Unindent();
            return members.Values.ToArray();
        }