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); }
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); }