Beispiel #1
0
        void Write(CustomAttribute ca)
        {
            if (ca is null)
            {
                helper.Error("The custom attribute is null");
                return;
            }

            // Check whether it's raw first. If it is, we don't care whether the ctor is
            // invalid. Just use the raw data.
            if (ca.IsRawBlob)
            {
                if ((ca.ConstructorArguments is not null && ca.ConstructorArguments.Count > 0) || (ca.NamedArguments is not null && ca.NamedArguments.Count > 0))
                {
                    helper.Error("Raw custom attribute contains arguments and/or named arguments");
                }
                writer.WriteBytes(ca.RawData);
                return;
            }

            if (ca.Constructor is null)
            {
                helper.Error("Custom attribute ctor is null");
                return;
            }

            var methodSig = GetMethodSig(ca.Constructor);

            if (methodSig is null)
            {
                helper.Error("Custom attribute ctor's method signature is invalid");
                return;
            }

            if (ca.ConstructorArguments.Count != methodSig.Params.Count)
            {
                helper.Error("Custom attribute arguments count != method sig arguments count");
            }
            if (methodSig.ParamsAfterSentinel is not null && methodSig.ParamsAfterSentinel.Count > 0)
            {
                helper.Error("Custom attribute ctor has parameters after the sentinel");
            }
            if (ca.NamedArguments.Count > ushort.MaxValue)
            {
                helper.Error("Custom attribute has too many named arguments");
            }

            if (ca.Constructor is MemberRef mrCtor && mrCtor.Class is TypeSpec owner && owner.TypeSig is GenericInstSig gis)
            {
                genericArguments = new GenericArguments();
                genericArguments.PushTypeArgs(gis.GenericArguments);
            }

            writer.WriteUInt16((ushort)1);

            int numArgs = Math.Min(methodSig.Params.Count, ca.ConstructorArguments.Count);

            for (int i = 0; i < numArgs; i++)
            {
                WriteValue(FixTypeSig(methodSig.Params[i]), ca.ConstructorArguments[i]);
            }

            int numNamedArgs = Math.Min((int)ushort.MaxValue, ca.NamedArguments.Count);

            writer.WriteUInt16((ushort)numNamedArgs);
            for (int i = 0; i < numNamedArgs; i++)
            {
                Write(ca.NamedArguments[i]);
            }
        }
        void Write(CustomAttribute ca)
        {
            if (ca == null)
            {
                helper.Error("The custom attribute is null");
                return;
            }

            // Check whether it's raw first. If it is, we don't care whether the ctor is
            // invalid. Just use the raw data.
            if (ca.IsRawBlob)
            {
                if ((ca.ConstructorArguments != null && ca.ConstructorArguments.Count > 0) || (ca.NamedArguments != null && ca.NamedArguments.Count > 0))
                {
                    helper.Error("Raw custom attribute contains arguments and/or named arguments");
                }
                writer.Write(ca.RawData);
                return;
            }

            if (ca.Constructor == null)
            {
                helper.Error("Custom attribute ctor is null");
                return;
            }

            var methodSig = GetMethodSig(ca.Constructor);

            if (methodSig == null)
            {
                helper.Error("Custom attribute ctor's method signature is invalid");
                return;
            }

            if (ca.ConstructorArguments.Count != methodSig.Params.Count)
            {
                helper.Error("Custom attribute arguments count != method sig arguments count");
            }
            if (methodSig.ParamsAfterSentinel != null && methodSig.ParamsAfterSentinel.Count > 0)
            {
                helper.Error("Custom attribute ctor has parameters after the sentinel");
            }
            if (ca.NamedArguments.Count > ushort.MaxValue)
            {
                helper.Error("Custom attribute has too many named arguments");
            }

            // A generic custom attribute isn't allowed by most .NET languages (eg. C#) but
            // the CLR probably supports it.
            var mrCtor = ca.Constructor as MemberRef;

            if (mrCtor != null)
            {
                var owner = mrCtor.Class as TypeSpec;
                if (owner != null)
                {
                    var gis = owner.TypeSig as GenericInstSig;
                    if (gis != null)
                    {
                        genericArguments = new GenericArguments();
                        genericArguments.PushTypeArgs(gis.GenericArguments);
                    }
                }
            }

            writer.Write((ushort)1);

            int numArgs = Math.Min(methodSig.Params.Count, ca.ConstructorArguments.Count);

            for (int i = 0; i < numArgs; i++)
            {
                WriteValue(FixTypeSig(methodSig.Params[i]), ca.ConstructorArguments[i]);
            }

            int numNamedArgs = Math.Min((int)ushort.MaxValue, ca.NamedArguments.Count);

            writer.Write((ushort)numNamedArgs);
            for (int i = 0; i < numNamedArgs; i++)
            {
                Write(ca.NamedArguments[i]);
            }
        }