Exemplo n.º 1
0
        private static void AnalyzeCall(SyntaxNodeAnalysisContext context, ISymbol migratableAttributeType)
        {
            var ct = context.CancellationToken;
            var typeDeclaration = (TypeDeclarationSyntax)context.Node;
            var attribute       = MigrationHashHelper.GetAttribute(typeDeclaration, migratableAttributeType, context.SemanticModel, ct);

            if (attribute == null)
            {
                return;
            }

            var typeSymbol       = context.SemanticModel.GetDeclaredSymbol(typeDeclaration, ct);
            var verifier         = new MigrationMethodVerifier(CanAssign(context));
            var migrationMethods = MigrationHashHelper.GetMigrationMethods(typeSymbol);

            var invalidMethods = verifier.VerifyMigrationMethods(migrationMethods)
                                 .Where(x => x.Result != VerificationResultEnum.Ok);

            foreach (var x in invalidMethods)
            {
                var method = typeSymbol.GetMembers()
                             .First(sy => sy.Name == x.Method.Name);
                Debug.Assert(method.Locations.Length == 1, "Method has multiple locations.");
                var diagnostic = Diagnostic.Create(Rule, method.Locations[0], method.Name, typeSymbol.Name, x.Result);
                context.ReportDiagnostic(diagnostic);
            }
        }
        public void VerifyMigrationMethodShouldWork()
        {
            var method             = typeof(TypeWithMigrationMethod0).GetMethod("Migrate_0", BindingFlags.NonPublic | BindingFlags.Static);
            var verificationResult = new MigrationMethodVerifier(VersionMemberName.CanAssign)
                                     .VerifyMigrationMethodSignature(VersionMemberName.GetMigrationMethod(method), null);

            verificationResult.Should().Be(VerificationResultEnum.Ok);
        }
        /// <summary>
        /// Try to migrate the serialized data to a newer version using migration methods from type unserializedDataType.
        /// </summary>
        /// <param name="serializedData"></param>
        /// <param name="unserializedDataType"></param>
        /// <param name="serializer"></param>
        /// <returns></returns>
        public Tuple <TSerializedData, bool> TryMigrate(TSerializedData serializedData, Type unserializedDataType, JsonSerializer serializer)
        {
            if (serializedData == null)
            {
                throw new ArgumentNullException(nameof(serializedData));
            }
            if (unserializedDataType == null)
            {
                throw new ArgumentNullException(nameof(unserializedDataType));
            }

            var migrationSettings = unserializedDataType.GetTypeInfo().GetCustomAttribute <MigratableAttribute>();

            if (migrationSettings == null)
            {
                return(Tuple.Create(serializedData, false));
            }


            var version = _VersionExtractor.GetVersion(serializedData);

            var allMigrationMethods = VersionMemberName
                                      .GetMigrationMethods(unserializedDataType)
                                      .ToList();

            var maxSupportedVersion = allMigrationMethods.LastOrDefault()?.ToVersion ?? 0;

            if (version > maxSupportedVersion)
            {
                throw new DataVersionTooHighException($"Trying to load data type '{unserializedDataType.FullName}' from json data " +
                                                      $"at version {version}." +
                                                      $" However current software only supports version {maxSupportedVersion}." +
                                                      " Please update your installation with a newwer version.");
            }

            var migrationMethods = allMigrationMethods
                                   .SkipWhile(m => m.ToVersion <= version)
                                   .ToList();

            var migrated = migrationMethods.Count > 0;

            try
            {
                serializedData = migrationMethods
                                 .Select(m => unserializedDataType.GetTypeInfo().GetDeclaredMethod(m.Name))
                                 .Aggregate(serializedData,
                                            (data, method) => ExecuteMigration(method, data, serializer));
            }
            catch (Exception e)
            {
                var migrationMethodVerifier = new MigrationMethodVerifier(VersionMemberName.CanAssign);

                var invalidMethod = migrationMethodVerifier.VerifyMigrationMethods(allMigrationMethods);
                foreach (var method in invalidMethod)
                {
                    method.ThrowIfInvalid(e);
                }

                // Exception doesn't come from invalid migration methods -> rethrow
                throw;
            }

            _VersionExtractor.SetVersion(serializedData, maxSupportedVersion);

            return(Tuple.Create(serializedData, migrated));
        }