Пример #1
0
 public IDisposable OpenType(BarfTypeDefinition definition)
 {
     Definition        = definition;
     SerializerBuilder = new BarfSerializerBuilder(definition);
     TesterBuilder     = new BarfTesterBuilder(definition);
     TypeDefinition    = Module.Types[Type.GetCecilFullName()];
     BarfSerializer    = new TypeDefinition(
         "AutoSerializer",
         TypeDefinition.Namespace,
         TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.NestedPrivate | TypeAttributes.BeforeFieldInit,
         Import(typeof(BarfSerializer <>).ResolveGenericType(Type)));
     BarfTester = new TypeDefinition(
         "BarfTester",
         TypeDefinition.Namespace,
         TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.NestedPrivate | TypeAttributes.BeforeFieldInit,
         Import(typeof(object)));
     return(new AnonymousDisposable(() =>
     {
         Definition = null;
         SerializerBuilder = null;
         TesterBuilder = null;
         TypeDefinition = null;
         BarfSerializer = null;
         BarfTester = null;
     }));
 }
Пример #2
0
        public BarfTesterBuilder(BarfTypeDefinition typeDefinition)
        {
            if (typeDefinition == null)
            {
                throw new ArgumentNullException("typeDefinition");
            }

            _def = typeDefinition;
        }
Пример #3
0
        public long BeginObject <T>()
        {
            var def = BarfTypeDefinition.Get <T>(true);

            return(BeginObject(def.CurrentVersion, def.MinVersion));
        }
Пример #4
0
        /// <summary>
        /// Instruments the specified assembly definition.
        /// </summary>
        /// <param name="assemblyDefinition">The assembly definition.</param>
        public void Instrument(AssemblyDefinition assemblyDefinition)
        {
            int eligibleTypeCount  = 0;
            int validTypeCount     = 0;
            var reflectionAssembly = GetAssembly(assemblyDefinition.Name.FullName);

            foreach (ModuleDefinition moduleDefinition in assemblyDefinition.Modules)
            {
                Module module = null;

                foreach (var mod in reflectionAssembly.GetModules(false))
                {
                    if (moduleDefinition.Name == moduleDefinition.Name)
                    {
                        module = mod;
                    }
                }

                if (module == null)
                {
                    throw new InvalidOperationException("Couldn't resolve module: " + moduleDefinition.Name);
                }

                try
                {
                    _context = new InstrumentationContext(moduleDefinition);

                    foreach (Type type in module.GetTypes())
                    {
                        if (!type.IsClass)
                        {
                            continue;
                        }

                        if (!BarfFormatter.IsSerializable(type))
                        {
                            continue;
                        }

                        var attribute = Attribute
                                        .GetCustomAttributes(type, typeof(SerializableClassAttribute), false)
                                        .OfType <SerializableClassAttribute>()
                                        .FirstOrDefault <SerializableClassAttribute>();

                        if (attribute.RuntimeOnly)
                        {
                            continue;
                        }

                        var barfTypeDef = BarfTypeDefinition.Get(type);

                        if (barfTypeDef == null)
                        {
                            // todo - remove once everything is supported
                            continue;
                        }

                        ++eligibleTypeCount;

                        if (type.IsGenericType)
                        {
                            continue;
                        }

                        Trace.WriteLine("Instrumenting - " + type.Name);

                        using (_context.OpenType(barfTypeDef))
                        {
                            _context.BarfSerializer.CustomAttributes.Add(new CustomAttribute(_context.Import(typeof(CompilerGeneratedAttribute).GetConstructor(Type.EmptyTypes))));
                            _context.TypeDefinition.NestedTypes.Add(_context.BarfSerializer);
                            _context.TypeDefinition.Module.Types.Add(_context.BarfSerializer);

                            GenerateDefaultCtor(_context.BarfSerializer, _context.BaseBarfSerializer);
                            GenerateCreateEmptyMethod();
                            GenerateSerializeMethod();
                            GenerateInnerDeserializeMethod();

                            _context.BarfTester.CustomAttributes.Add(new CustomAttribute(_context.Import(typeof(CompilerGeneratedAttribute).GetConstructor(Type.EmptyTypes))));
                            _context.BarfTester.Interfaces.Add(_context.BarfTesterInterface);
                            _context.TypeDefinition.NestedTypes.Add(_context.BarfTester);
                            _context.TypeDefinition.Module.Types.Add(_context.BarfTester);

                            GenerateDefaultCtor(_context.BarfTester, typeof(object));

                            GenerateFillMethod();
                            GenerateAssertAreEqualMethod();


                            ++validTypeCount;
                        }
                    }
                }
                finally
                {
                    _context = null;
                }
            }
            Trace.TraceInformation("{0} - {1} of {2} eligible types were generated in {3}", GetType().Name, validTypeCount, eligibleTypeCount, assemblyDefinition.Name.Name);
        }
Пример #5
0
        private static BarfTypeDefinition Create(Type type)
        {
            var parts  = new List <PartDefinition>();
            var errors = new List <string>();
            var result = new BarfTypeDefinition
            {
                Type   = type,
                Errors = new ReadOnlyCollection <string>(errors),
                Parts  = new ReadOnlyCollection <PartDefinition>(parts)
            };

            try
            {
                var classAttribute = (SerializableClassAttribute)Attribute.GetCustomAttribute(type, typeof(SerializableClassAttribute), false);

                if (classAttribute == null)
                {
                    errors.Add(type.Name + " does not define a " + typeof(SerializableAttribute).Name);
                    return(result);
                }

                var typePartDef = PartDefinition.Create(type);

                if (typePartDef != null)
                {
                    parts.Add(typePartDef);
                }

                const BindingFlags flags
                    = BindingFlags.Instance
                      | BindingFlags.Public
                      | BindingFlags.NonPublic
                      | BindingFlags.DeclaredOnly;

                parts.AddRange(PartDefinition.CreateInheritedParts(type));

                foreach (var member in type.GetMembers(flags))
                {
                    if (member.DeclaringType != type)
                    {
                        continue;
                    }
                    if (member.MemberType != MemberTypes.Property && member.MemberType != MemberTypes.Field)
                    {
                        continue;
                    }

                    var partDefinition = PartDefinition.Create(member);

                    if (partDefinition == null)
                    {
                        continue;
                    }

                    if (partDefinition.IsDynamic)
                    {
                        if (partDefinition.Type.IsValueType)
                        {
                            // value types may not be dynamic
                            return(result);
                        }
                    }

                    parts.Add(partDefinition);
                }

                parts.Sort(BarfPartInfoComparer.Default);

                result.CurrentVersion = result.Parts
                                        .Select(part => part.Version)
                                        .Concat(new[] { classAttribute.MinVersion })
                                        .Max <int>();


                // before we would guess the min version if it was zero
                // by taking the lowest property version. However
                // if an empty class defining no parts will be version
                // zero. If a property is added at version 1 min version
                // will then become 1 making it impossible to deserialize
                // the older empty class streams.
                result.MinVersion = classAttribute.MinVersion;

                result.MinDeserializeVersion = Math.Max(classAttribute.MinDeserializeVersion, 0);

                result.LegacyVersion = classAttribute.LegacyVersion;

                if (result.LegacyVersion >= 0)
                {
                    var method = type.ResolveMethod("Deserialize", typeof(IPrimitiveReader), typeof(int));
                    if (method != null && method.IsStatic)
                    {
                        method = null;
                    }
                    if (method == null && result.LegacyVersion > 0)
                    {
                        errors.Add("LegacyVersion=" + result.LegacyVersion + " but no method void Deserialize(IPrimitiveReader, int) was defined.");
                    }
                    else
                    {
                        result.LegacyDeserializeMethod = method;
                    }
                }

                result.IsForwardCompatible = typeof(ISerializationInfo).IsAssignableFrom(type);
            }
            catch (Exception ex)
            {
                errors.Add(ex.ToString());
                return(result);
            }
            return(result);
        }
        /// <summary>
        /// Begins a region of code that deserializes a barf type.
        /// </summary>
        public BarfObjectHeader BeginObject <T>()
        {
            var def = BarfTypeDefinition.Get <T>(true);

            bool deserializeTypeTable = false;

            if (StreamHeader == null)
            {
                StreamHeader = BarfStreamHeader.ReadFrom(Reader);
                if (StreamHeader.FrameworkVersion > BarfFormatter.MaxFrameworkVersion)
                {
                    string message = string.Format(
                        "Encountered a BARF formatted stream with FrameworkVersion=\"{0}\" but MaxFrameworkVersion=\"{1}\".",
                        StreamHeader.FrameworkVersion,
                        BarfFormatter.MaxFrameworkVersion);
                    throw new UnhandledVersionException(message);
                }

                deserializeTypeTable = StreamHeader.Flags.IsSet(HeaderFlags.HasNameTable);
            }

            var objectHeader = BarfObjectHeader.ReadFrom(Reader);

            if (!objectHeader.IsNull)
            {
                if (objectHeader.Version < def.MinVersion)
                {
                    var message = string.Format(
                        "Binary data was encoded with Version=\"{0}\" but the current MinVersion=\"{1}\".",
                        objectHeader.Version,
                        def.MinVersion);
                    throw new UnhandledVersionException(message);
                }

                if (def.CurrentVersion < objectHeader.MinVersion)
                {
                    var message = string.Format(
                        "Binary data was encoded with a MinVersion=\"{0}\" but CurrentVersion=\"{1}\" is less than that.",
                        objectHeader.MinVersion,
                        def.CurrentVersion);
                    throw new UnhandledVersionException(message);
                }

                if (objectHeader.Version < def.MinDeserializeVersion)
                {
                    var message = string.Format(
                        "Binary data is Version=\"{0}\" but MinDeserializeVersion=\"{1}\".",
                        objectHeader.Version,
                        def.MinDeserializeVersion);
                    throw new UnhandledVersionException(message);
                }
            }

            if (deserializeTypeTable)
            {
                var currentPosition = Reader.BaseStream.Position;

                Reader.BaseStream.Seek(objectHeader.Length, SeekOrigin.Current);

                TypeTable = BarfTypeTable.ReadFrom(Reader);

                _streamEnd = Reader.BaseStream.Position;

                Reader.BaseStream.Seek(currentPosition, SeekOrigin.Begin);
            }

            ++_objectDepth;
            return(objectHeader);
        }
        public void RaiseInvalidData <T>(BarfObjectHeader header, string message)
        {
            var builder = new StringBuilder();
            var w       = XmlWriter.Create(builder, new XmlWriterSettings
            {
                Indent              = true,
                IndentChars         = "\t",
                OmitXmlDeclaration  = true,
                ConformanceLevel    = ConformanceLevel.Fragment,
                NewLineChars        = Environment.NewLine,
                NewLineHandling     = NewLineHandling.Entitize,
                NewLineOnAttributes = false
            });

            w.WriteStartElement("Details");
            {
                if (!string.IsNullOrEmpty(message))
                {
                    w.WriteElementString("Message", message);
                }
                w.WriteElementString("Type", typeof(T).ToString());
                w.WriteElementString("Position", Reader.BaseStream.Position.ToString());
                w.WriteElementString("ObjectDepth", _objectDepth.ToString());
                if (header != null)
                {
                    w.WriteStartElement("ObjectHeader");
                    {
                        w.WriteElementString("IsNull", header.IsNull.ToString());
                        if (!header.IsNull)
                        {
                            w.WriteElementString("Version", header.Version.ToString());
                            w.WriteElementString("MinVersion", header.MinVersion.ToString());
                            w.WriteElementString("Length", header.Length.ToString());
                            w.WriteElementString("StartPosition", header.StartPosition.ToString());
                            w.WriteElementString("EndPosition", header.EndPosition.ToString());
                        }
                    }
                    w.WriteEndElement();
                }
                w.WriteStartElement("CurrentDefinition");
                {
                    var def = BarfTypeDefinition.Get <T>(false);
                    if (def == null || !def.IsValid)
                    {
                        w.WriteElementString("Error", "Couldn't load definition for type - " + typeof(T));
                    }
                    else
                    {
                        w.WriteElementString("CurrentVersion", def.CurrentVersion.ToString());
                        w.WriteElementString("MinVersion", def.MinVersion.ToString());
                        w.WriteElementString("MinDeserializeVersion", def.MinDeserializeVersion.ToString());
                    }
                }
                w.WriteEndElement();
                w.WriteStartElement("StreamHeader");
                {
                    w.WriteElementString("FrameworkVersion", StreamHeader.FrameworkVersion.ToString());
                    w.WriteElementString("Flags", StreamHeader.Flags.ToString());
                    w.WriteElementString("Length", StreamHeader.Length.ToString());
                }
                w.WriteEndElement();
            }
            w.WriteEndElement();
            w.Flush();

            throw new InvalidDataException(builder.ToString());
        }