/// <summary>
        /// Generates the class for the provided grain types.
        /// </summary>
        /// <param name="grainType">
        /// The grain interface type.
        /// </param>
        /// <returns>
        /// The generated class.
        /// </returns>
        internal static TypeDeclarationSyntax GenerateClass(Type grainType)
        {
            var baseTypes = new List<BaseTypeSyntax> { SF.SimpleBaseType(typeof(IGrainMethodInvoker).GetTypeSyntax()) };

            var grainTypeInfo = grainType.GetTypeInfo();
            var genericTypes = grainTypeInfo.IsGenericTypeDefinition
                                   ? grainTypeInfo.GetGenericArguments()
                                         .Select(_ => SF.TypeParameter(_.ToString()))
                                         .ToArray()
                                   : new TypeParameterSyntax[0];

            // Create the special method invoker marker attribute.
            var interfaceId = GrainInterfaceUtils.GetGrainInterfaceId(grainType);
            var interfaceIdArgument = SF.LiteralExpression(SyntaxKind.NumericLiteralExpression, SF.Literal(interfaceId));
            var grainTypeArgument = SF.TypeOfExpression(grainType.GetTypeSyntax(includeGenericParameters: false));
            var attributes = new List<AttributeSyntax>
            {
                CodeGeneratorCommon.GetGeneratedCodeAttributeSyntax(),
                SF.Attribute(typeof(MethodInvokerAttribute).GetNameSyntax())
                    .AddArgumentListArguments(
                        SF.AttributeArgument(grainType.GetParseableName().GetLiteralExpression()),
                        SF.AttributeArgument(interfaceIdArgument),
                        SF.AttributeArgument(grainTypeArgument)),
                SF.Attribute(typeof(ExcludeFromCodeCoverageAttribute).GetNameSyntax())
            };

            var members = new List<MemberDeclarationSyntax>
            {
                GenerateInvokeMethod(grainType),
                GenerateInterfaceIdProperty(grainType)
            };

            // If this is an IGrainExtension, make the generated class implement IGrainExtensionMethodInvoker.
            if (typeof(IGrainExtension).IsAssignableFrom(grainType))
            {
                baseTypes.Add(SF.SimpleBaseType(typeof(IGrainExtensionMethodInvoker).GetTypeSyntax()));
                members.Add(GenerateExtensionInvokeMethod(grainType));
            }

            var classDeclaration =
                SF.ClassDeclaration(
                    CodeGeneratorCommon.ClassPrefix + TypeUtils.GetSuitableClassName(grainType) + ClassSuffix)
                    .AddModifiers(SF.Token(SyntaxKind.InternalKeyword))
                    .AddBaseListTypes(baseTypes.ToArray())
                    .AddConstraintClauses(grainType.GetTypeConstraintSyntax())
                    .AddMembers(members.ToArray())
                    .AddAttributeLists(SF.AttributeList().AddAttributes(attributes.ToArray()));
            if (genericTypes.Length > 0)
            {
                classDeclaration = classDeclaration.AddTypeParameterListParameters(genericTypes);
            }

            return classDeclaration;
        }
Example #2
0
        private static void ConsiderType(
            Type type,
            bool runtime,
            Assembly targetAssembly,
            ISet<Type> includedTypes)
        {
            // The module containing the serializer.
            var module = runtime || type.Assembly != targetAssembly ? null : type.Module;
            var typeInfo = type.GetTypeInfo();

            // If a type was encountered which can be accessed and is marked as [Serializable], process it for serialization.
            if (typeInfo.IsSerializable)
                RecordType(type, module, targetAssembly, includedTypes);
            
            ConsiderGenericBaseTypeArguments(typeInfo, module, targetAssembly, includedTypes);
            ConsiderGenericInterfacesArguments(typeInfo, module, targetAssembly, includedTypes);

            // Collect the types which require code generation.
            if (GrainInterfaceData.IsGrainInterface(type))
            {
                if (Logger.IsVerbose2) Logger.Verbose2("Will generate code for: {0}", type.GetParseableName());

                includedTypes.Add(type);
            }
        }
Example #3
0
 /// <summary>
 /// </summary>
 /// <param name="forGrainType">type argument</param>
 public GrainReferenceAttribute(Type forGrainType)
 {
     GrainType = forGrainType;
     ForGrainType = forGrainType.GetParseableName();
 }
Example #4
0
 /// <summary>
 /// </summary>
 /// <param name="forGrainType">type argument</param>
 public GrainStateAttribute(Type forGrainType)
 {
     GrainType = forGrainType;
     ForGrainType = forGrainType.GetParseableName();
 }
Example #5
0
 /// <summary>
 /// </summary>
 /// <param name="forGrainType">type argument</param>
 public SerializerAttribute(Type forGrainType)
 {
     GrainType = forGrainType;
     ForGrainType = forGrainType.GetParseableName();
 }
Example #6
0
 private static MemberDeclarationSyntax GenerateInterfaceNameProperty(Type grainType)
 {
     var propertyName = TypeUtils.Member((GrainReference _) => _.InterfaceName);
     var returnValue = grainType.GetParseableName().GetLiteralExpression();
     return
         SF.PropertyDeclaration(typeof(string).GetTypeSyntax(), propertyName.Name)
             .AddAccessorListAccessors(
                 SF.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
                     .AddBodyStatements(SF.ReturnStatement(returnValue)))
             .AddModifiers(SF.Token(SyntaxKind.PublicKeyword), SF.Token(SyntaxKind.OverrideKeyword));
 }
Example #7
0
        private static void ConsiderType(
            Type type,
            bool runtime,
            Assembly targetAssembly,
            ISet<Type> includedTypes)
        {
            // The module containing the serializer.
            var module = runtime ? null : type.Module;
            var typeInfo = type.GetTypeInfo();

            // If a type was encountered which can be accessed and is marked as [Serializable], process it for serialization.
            if (typeInfo.IsSerializable)
                RecordType(type, module, targetAssembly, includedTypes);

            Type grainStateType;
            // If a type extends Grain<T>, add T to the list of candidates for serialization
            if (IsPersistentGrain(typeInfo, out grainStateType))
                RecordType(grainStateType, module, targetAssembly, includedTypes);

            // Collect the types which require code generation.
            if (GrainInterfaceData.IsGrainInterface(type))
            {
                if (Logger.IsVerbose2) Logger.Verbose2("Will generate code for: {0}", type.GetParseableName());

                includedTypes.Add(type);
            }
        }
Example #8
0
        private static void ConsiderType(
            Type type,
            bool runtime,
            Assembly targetAssembly,
            ISet<Type> includedTypes)
        {
            // The module containing the serializer.
            var module = runtime ? null : type.Module;
            var typeInfo = type.GetTypeInfo();

            // Every type which is encountered must be considered for serialization.
            if (!typeInfo.IsNested && !typeInfo.IsGenericParameter && typeInfo.IsSerializable)
            {
                // If a type was encountered which can be accessed, process it for serialization.
                if (SerializerGenerationManager.RecordTypeToGenerate(type, module, targetAssembly))
                {
                    includedTypes.Add(type);
                }
            }

            // Collect the types which require code generation.
            if (GrainInterfaceData.IsGrainInterface(type))
            {
                if (Logger.IsVerbose2)
                {
                    Logger.Verbose2("Will generate code for: {0}", type.GetParseableName());
                }

                includedTypes.Add(type);
            }
        }
Example #9
0
        private static void ConsiderType(
            Type type,
            bool runtime,
            Assembly targetAssembly,
            ISet<Type> includedTypes,
            bool considerForSerialization = false)
        {
            // The module containing the serializer.
            var typeInfo = type.GetTypeInfo();
            var module = runtime || !Equals(typeInfo.Assembly, targetAssembly) ? null : typeInfo.Module;

            // If a type was encountered which can be accessed and is marked as [Serializable], process it for serialization.
            if (considerForSerialization)
            {
                RecordType(type, module, targetAssembly, includedTypes);
            }
            
            // Consider generic arguments to base types and implemented interfaces for code generation.
            ConsiderGenericBaseTypeArguments(typeInfo, module, targetAssembly, includedTypes);
            ConsiderGenericInterfacesArguments(typeInfo, module, targetAssembly, includedTypes);
            
            // Include grain interface types.
            if (GrainInterfaceUtils.IsGrainInterface(type))
            {
                // If code generation is being performed at runtime, the interface must be accessible to the generated code.
                if (!runtime || TypeUtilities.IsTypePublic(type))
                {
                    if (Logger.IsVerbose2) Logger.Verbose2("Will generate code for: {0}", type.GetParseableName());

                    includedTypes.Add(type);
                }
            }
        }