Example #1
0
        internal bool RecordTypeToGenerate(Type t, Module module, Assembly targetAssembly)
        {
            if (TypeUtilities.IsTypeIsInaccessibleForSerialization(t, module, targetAssembly))
            {
                return(false);
            }

            var typeInfo = t.GetTypeInfo();

            if (typeInfo.IsGenericParameter || processedTypes.Contains(t) || typesToProcess.Contains(t) ||
                typeof(Exception).GetTypeInfo().IsAssignableFrom(t) ||
                typeof(Delegate).GetTypeInfo().IsAssignableFrom(t) ||
                typeof(Task <>).GetTypeInfo().IsAssignableFrom(t))
            {
                return(false);
            }

            if (typeInfo.IsArray)
            {
                RecordTypeToGenerate(typeInfo.GetElementType(), module, targetAssembly);
                return(false);
            }

            if (typeInfo.IsNestedFamily || typeInfo.IsNestedPrivate)
            {
                log.Warn(
                    ErrorCode.CodeGenIgnoringTypes,
                    "Skipping serializer generation for nested type {0}. If this type is used frequently, you may wish to consider making it non-nested.",
                    t.Name);
                return(false);
            }

            if (t.IsConstructedGenericType)
            {
                var args = typeInfo.GetGenericArguments();
                foreach (var arg in args)
                {
                    RecordTypeToGenerate(arg, module, targetAssembly);
                }
            }

            if (typeInfo.IsInterface || typeInfo.IsAbstract || t == typeof(object) || t == typeof(void) ||
                GrainInterfaceUtils.IsTaskType(t))
            {
                return(false);
            }

            if (t.IsConstructedGenericType)
            {
                return(RecordTypeToGenerate(typeInfo.GetGenericTypeDefinition(), module, targetAssembly));
            }

            if (typeInfo.IsOrleansPrimitive() || this.serializationManager.HasSerializer(t) ||
                typeof(IAddressable).GetTypeInfo().IsAssignableFrom(t))
            {
                return(false);
            }

            if (typeInfo.Namespace != null && (typeInfo.Namespace.Equals("System") || typeInfo.Namespace.StartsWith("System.")))
            {
                var message = "System type " + t.Name + " may require a custom serializer for optimal performance. "
                              + "If you use arguments of this type a lot, consider submitting a pull request to https://github.com/dotnet/orleans/ to add a custom serializer for it.";
                log.Warn(ErrorCode.CodeGenSystemTypeRequiresSerializer, message);
                return(false);
            }

            if (TypeUtils.HasAllSerializationMethods(t))
            {
                return(false);
            }

            // This check is here and not within TypeUtilities.IsTypeIsInaccessibleForSerialization() to prevent potential infinite recursions
            var skipSerializerGeneration =
                t.GetAllFields().Any(field => this.IsFieldInaccessibleForSerialization(module, targetAssembly, field));

            if (skipSerializerGeneration)
            {
                return(false);
            }

            typesToProcess.Add(t);
            return(true);
        }
Example #2
0
        internal bool RecordType(Type t, Assembly targetAssembly, string logContext)
        {
            if (!TypeUtilities.IsAccessibleFromAssembly(t, targetAssembly))
            {
                return(false);
            }

            if (t.IsGenericParameter || processedTypes.Contains(t) || typesToProcess.Contains(t) ||
                typesToIgnore.Contains(t) ||
                typeof(Exception).IsAssignableFrom(t) ||
                typeof(Delegate).IsAssignableFrom(t) ||
                typeof(Task <>).IsAssignableFrom(t))
            {
                return(false);
            }

            if (t.IsArray)
            {
                RecordType(t.GetElementType(), targetAssembly, logContext);
                return(false);
            }

            if (t.IsNestedFamily || t.IsNestedPrivate)
            {
                log.Warn(
                    ErrorCode.CodeGenIgnoringTypes,
                    "Skipping serializer generation for nested type {0}. If this type is used frequently, you may wish to consider making it non-nested.",
                    t.Name);
                return(false);
            }

            if (t.IsConstructedGenericType)
            {
                var args = t.GetGenericArguments();
                foreach (var arg in args)
                {
                    if (log.IsEnabled(LogLevel.Trace))
                    {
                        logContext = "generic argument of type " + t.GetLogFormat();
                    }
                    RecordType(arg, targetAssembly, logContext);
                }
            }

            if (t.IsInterface || t.IsAbstract || t == typeof(object) || t == typeof(void) ||
                GrainInterfaceUtils.IsTaskType(t))
            {
                return(false);
            }

            if (t.IsConstructedGenericType)
            {
                return(RecordType(t.GetGenericTypeDefinition(), targetAssembly, logContext));
            }

            if (t.IsOrleansPrimitive() || this.HasSerializer(t) ||
                typeof(IAddressable).IsAssignableFrom(t))
            {
                return(false);
            }

            if (t.Namespace != null && (t.Namespace.Equals("System") || t.Namespace.StartsWith("System.")))
            {
                if (log.IsEnabled(LogLevel.Debug))
                {
                    var message = $"System type {t.Name} may require a custom serializer for optimal performance. " +
                                  "If you use arguments of this type a lot, consider submitting a pull request to https://github.com/dotnet/orleans/ to add a custom serializer for it.";
                    log.Debug(ErrorCode.CodeGenSystemTypeRequiresSerializer, message);
                }
                return(false);
            }

            if (TypeUtils.HasAllSerializationMethods(t))
            {
                return(false);
            }

            // For every field which is not marked as [NonSerialized], check that it is accessible from code.
            // If any of those fields are not accessible, then a serializer cannot be generated for this type.
            var skipSerializerGeneration =
                t.GetAllFields().Where(field => !field.IsNotSerialized())
                .Any(field => !TypeUtilities.IsAccessibleFromAssembly(field.FieldType, targetAssembly));

            if (skipSerializerGeneration)
            {
                return(false);
            }

            // Do not generate serializers for classes which require the use of serialization hooks.
            // Instead, a fallback serializer which supports those hooks can be used.
            if (DotNetSerializableUtilities.HasSerializationHookAttributes(t))
            {
                return(false);
            }

            if (!typesToProcess.Add(t))
            {
                return(true);
            }

            if (log.IsEnabled(LogLevel.Trace))
            {
                log.LogTrace($"Will generate serializer for type {t.GetLogFormat()} encountered from {logContext}");
            }

            var interfaces = t.GetInterfaces().Where(x => x.IsConstructedGenericType);

            if (log.IsEnabled(LogLevel.Trace))
            {
                logContext = "generic argument of implemented interface on type " + t.GetLogFormat();
            }
            foreach (var arg in interfaces.SelectMany(v => v.GetGenericArguments()))
            {
                RecordType(arg, targetAssembly, logContext);
            }

            return(true);
        }
        internal bool RecordTypeToGenerate(Type t, Assembly targetAssembly)
        {
            if (!TypeUtilities.IsAccessibleFromAssembly(t, targetAssembly))
            {
                return(false);
            }

            var typeInfo = t.GetTypeInfo();

            if (typeInfo.IsGenericParameter || processedTypes.Contains(t) || typesToProcess.Contains(t) ||
                typeof(Exception).GetTypeInfo().IsAssignableFrom(t) ||
                typeof(Delegate).GetTypeInfo().IsAssignableFrom(t) ||
                typeof(Task <>).GetTypeInfo().IsAssignableFrom(t))
            {
                return(false);
            }

            if (typeInfo.IsArray)
            {
                RecordTypeToGenerate(typeInfo.GetElementType(), targetAssembly);
                return(false);
            }

            if (typeInfo.IsNestedFamily || typeInfo.IsNestedPrivate)
            {
                log.Warn(
                    ErrorCode.CodeGenIgnoringTypes,
                    "Skipping serializer generation for nested type {0}. If this type is used frequently, you may wish to consider making it non-nested.",
                    t.Name);
                return(false);
            }

            if (t.IsConstructedGenericType)
            {
                var args = typeInfo.GetGenericArguments();
                foreach (var arg in args)
                {
                    RecordTypeToGenerate(arg, targetAssembly);
                }
            }

            if (typeInfo.IsInterface || typeInfo.IsAbstract || t == typeof(object) || t == typeof(void) ||
                GrainInterfaceUtils.IsTaskType(t))
            {
                return(false);
            }

            if (t.IsConstructedGenericType)
            {
                return(RecordTypeToGenerate(typeInfo.GetGenericTypeDefinition(), targetAssembly));
            }

            if (typeInfo.IsOrleansPrimitive() || this.serializationManager.HasSerializer(t) ||
                typeof(IAddressable).GetTypeInfo().IsAssignableFrom(t))
            {
                return(false);
            }

            if (typeInfo.Namespace != null && (typeInfo.Namespace.Equals("System") || typeInfo.Namespace.StartsWith("System.")))
            {
                var message = "System type " + t.Name + " may require a custom serializer for optimal performance. "
                              + "If you use arguments of this type a lot, consider submitting a pull request to https://github.com/dotnet/orleans/ to add a custom serializer for it.";
                log.Debug(ErrorCode.CodeGenSystemTypeRequiresSerializer, message);
                return(false);
            }

            if (TypeUtils.HasAllSerializationMethods(t))
            {
                return(false);
            }

            // For every field which is not marked as [NonSerialized], check that it is accessible from code.
            // If any of those fields are not accessible, then a serializer cannot be generated for this type.
            var skipSerializerGeneration =
                t.GetAllFields().Where(field => !field.IsNotSerialized())
                .Any(field => !TypeUtilities.IsAccessibleFromAssembly(field.FieldType, targetAssembly));

            if (skipSerializerGeneration)
            {
                return(false);
            }

            typesToProcess.Add(t);
            return(true);
        }