/// <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; }
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); } }
/// <summary> /// </summary> /// <param name="forGrainType">type argument</param> public GrainReferenceAttribute(Type forGrainType) { GrainType = forGrainType; ForGrainType = forGrainType.GetParseableName(); }
/// <summary> /// </summary> /// <param name="forGrainType">type argument</param> public GrainStateAttribute(Type forGrainType) { GrainType = forGrainType; ForGrainType = forGrainType.GetParseableName(); }
/// <summary> /// </summary> /// <param name="forGrainType">type argument</param> public SerializerAttribute(Type forGrainType) { GrainType = forGrainType; ForGrainType = forGrainType.GetParseableName(); }
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)); }
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); } }
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); } }
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); } } }