/// <summary>
        /// Generates the class for the provided grain types.
        /// </summary>
        internal static TypeDeclarationSyntax GenerateClass(WellKnownTypes wellKnownTypes, GrainInterfaceDescription description)
        {
            var generatedTypeName = description.InvokerTypeName;
            var grainType         = description.Type;
            var baseTypes         = new List <BaseTypeSyntax> {
                SimpleBaseType(wellKnownTypes.IGrainMethodInvoker.ToTypeSyntax())
            };

            var genericTypes = grainType.GetHierarchyTypeParameters()
                               .Select(_ => TypeParameter(_.ToString()))
                               .ToArray();

            // Create the special method invoker marker attribute.
            var interfaceId         = description.InterfaceId;
            var interfaceIdArgument = interfaceId.ToHexLiteral();
            var grainTypeArgument   = TypeOfExpression(grainType.WithoutTypeParameters().ToTypeSyntax());
            var attributes          = new List <AttributeSyntax>
            {
                GeneratedCodeAttributeGenerator.GetGeneratedCodeAttributeSyntax(wellKnownTypes),
                Attribute(wellKnownTypes.MethodInvokerAttribute.ToNameSyntax())
                .AddArgumentListArguments(
                    AttributeArgument(grainTypeArgument),
                    AttributeArgument(interfaceIdArgument)),
                Attribute(wellKnownTypes.ExcludeFromCodeCoverageAttribute.ToNameSyntax())
            };

            var genericInvokerFields = GenerateGenericInvokerFields(wellKnownTypes, description.Methods);
            var members = new List <MemberDeclarationSyntax>(genericInvokerFields)
            {
                GenerateInvokeMethod(wellKnownTypes, grainType),
                GrainInterfaceCommon.GenerateInterfaceIdProperty(wellKnownTypes, description),
                GrainInterfaceCommon.GenerateInterfaceVersionProperty(wellKnownTypes, description)
            };

            // If this is an IGrainExtension, make the generated class implement IGrainExtensionMethodInvoker.
            if (grainType.HasInterface(wellKnownTypes.IGrainExtension))
            {
                baseTypes.Add(SimpleBaseType(wellKnownTypes.IGrainExtensionMethodInvoker.ToTypeSyntax()));
                members.Add(GenerateExtensionInvokeMethod(wellKnownTypes, grainType));
            }

            var classDeclaration =
                ClassDeclaration(generatedTypeName)
                .AddModifiers(Token(SyntaxKind.InternalKeyword))
                .AddBaseListTypes(baseTypes.ToArray())
                .AddConstraintClauses(grainType.GetTypeConstraintSyntax())
                .AddMembers(members.ToArray())
                .AddAttributeLists(AttributeList().AddAttributes(attributes.ToArray()));

            if (genericTypes.Length > 0)
            {
                classDeclaration = classDeclaration.AddTypeParameterListParameters(genericTypes);
            }

            return(classDeclaration);
        }
        /// <summary>
        /// Generates the class for the provided grain types.
        /// </summary>
        internal TypeDeclarationSyntax GenerateClass(GrainInterfaceDescription description)
        {
            var generatedTypeName = description.ReferenceTypeName;
            var grainType         = description.Type;
            var genericTypes      = grainType.GetHierarchyTypeParameters()
                                    .Select(_ => TypeParameter(_.ToString()))
                                    .ToArray();

            // Create the special marker attribute.
            var grainTypeArgument = TypeOfExpression(grainType.WithoutTypeParameters().ToTypeSyntax());

            var attributes = AttributeList()
                             .AddAttributes(
                GeneratedCodeAttributeGenerator.GetGeneratedCodeAttributeSyntax(wellKnownTypes),
                Attribute(wellKnownTypes.SerializableAttribute.ToNameSyntax()),
                Attribute(wellKnownTypes.ExcludeFromCodeCoverageAttribute.ToNameSyntax()),
                Attribute(wellKnownTypes.GrainReferenceAttribute.ToNameSyntax())
                .AddArgumentListArguments(AttributeArgument(grainTypeArgument)));

            var classDeclaration =
                ClassDeclaration(generatedTypeName)
                .AddModifiers(Token(SyntaxKind.InternalKeyword))
                .AddBaseListTypes(
                    SimpleBaseType(wellKnownTypes.GrainReference.ToTypeSyntax()),
                    SimpleBaseType(grainType.ToTypeSyntax()))
                .AddConstraintClauses(grainType.GetTypeConstraintSyntax())
                .AddMembers(GenerateConstructors(generatedTypeName))
                .AddMembers(
                    GrainInterfaceCommon.GenerateInterfaceIdProperty(this.wellKnownTypes, description).AddModifiers(Token(SyntaxKind.OverrideKeyword)),
                    GrainInterfaceCommon.GenerateInterfaceVersionProperty(this.wellKnownTypes, description).AddModifiers(Token(SyntaxKind.OverrideKeyword)),
                    GenerateInterfaceNameProperty(description),
                    GenerateIsCompatibleMethod(description),
                    GenerateGetMethodNameMethod(description))
                .AddMembers(GenerateInvokeMethods(description))
                .AddAttributeLists(attributes);

            if (genericTypes.Length > 0)
            {
                classDeclaration = classDeclaration.AddTypeParameterListParameters(genericTypes);
            }

            if (this.options.DebuggerStepThrough)
            {
                var debuggerStepThroughAttribute = Attribute(this.wellKnownTypes.DebuggerStepThroughAttribute.ToNameSyntax());
                classDeclaration = classDeclaration.AddAttributeLists(AttributeList().AddAttributes(debuggerStepThroughAttribute));
            }

            return(classDeclaration);
        }