Example #1
0
        protected virtual CodeTypeDeclaration GetStateClass(
            GrainInterfaceData grainInterfaceData,
            Action <Type> referred,
            string stateClassBaseName,
            string stateClassName,
            out bool hasStateClass)
        {
            var sourceType = grainInterfaceData.Type;

            stateClassName = FixupTypeName(stateClassName);
            CodeTypeParameterCollection genericTypeParams = grainInterfaceData.GenericTypeParams;

            Func <Type, bool> nonamespace = t => CurrentNamespace == t.Namespace || ReferencedNamespaces.Contains(t.Namespace);

            Type persistentInterface = GetPersistentInterface(sourceType);
            Dictionary <string, PropertyInfo> asyncProperties = GrainInterfaceData.GetPersistentProperties(persistentInterface)
                                                                .ToDictionary(p => p.Name.Substring(p.Name.LastIndexOf('.') + 1), p => p);

            Dictionary <string, string> properties = asyncProperties.ToDictionary(p => p.Key,
                                                                                  p => GetGenericTypeName(GrainInterfaceData.GetPromptType(p.Value.PropertyType), referred, nonamespace));

            var stateClass = new CodeTypeDeclaration(stateClassBaseName);

            if (genericTypeParams != null)
            {
                stateClass.TypeParameters.AddRange(genericTypeParams);
            }
            stateClass.IsClass = true;

            if (persistentInterface != null)
            {
                stateClass.TypeAttributes = persistentInterface.IsPublic ? TypeAttributes.Public : TypeAttributes.NotPublic;
            }
            else
            {
                stateClass.TypeAttributes = TypeAttributes.Public;
            }

            stateClass.BaseTypes.Add(new CodeTypeReference(typeof(GrainState), CodeTypeReferenceOptions.GlobalReference));
            MarkAsGeneratedCode(stateClass);
            referred(typeof(GrainState));

            if (persistentInterface != null)
            {
                stateClass.BaseTypes.Add(new CodeTypeReference(GetGenericTypeName(persistentInterface, referred, nonamespace)));
            }

            stateClass.CustomAttributes.Add(new CodeAttributeDeclaration(typeof(SerializableAttribute).Name));
            stateClass.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeTypeReference(typeof(GrainStateAttribute), CodeTypeReferenceOptions.GlobalReference),
                                                                         new CodeAttributeArgument(new CodePrimitiveExpression(grainInterfaceData.Type.Namespace + "." + TypeUtils.GetParameterizedTemplateName(grainInterfaceData.Type)))));

            referred(typeof(SerializableAttribute));
            referred(typeof(OnDeserializedAttribute));

            var initStateFields = new CodeMemberMethod {
                Name = "InitStateFields"
            };

            initStateFields.Attributes = (initStateFields.Attributes & ~MemberAttributes.AccessMask) | MemberAttributes.Private;
            foreach (var peoperty in asyncProperties)
            {
                Type propertyType = peoperty.Value.PropertyType;

                bool noCreateNew = propertyType.IsPrimitive || typeof(string).IsAssignableFrom(propertyType) || // Primative types
                                   propertyType.IsAbstract || propertyType.IsInterface || propertyType.IsGenericParameter || // No concrete implementation
                                   propertyType.GetConstructor(Type.EmptyTypes) == null; // No default constructor

                var initExpression = noCreateNew                                         // Pre-initialize this type to default value
                    ? (CodeExpression) new CodeDefaultValueExpression(new CodeTypeReference(GetGenericTypeName(propertyType, referred, nonamespace)))
                    : new CodeObjectCreateExpression(new CodeTypeReference(GetGenericTypeName(propertyType, referred, nonamespace)));

                initStateFields.Statements.Add(new CodeAssignStatement(
                                                   new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), peoperty.Key),
                                                   initExpression));
            }

            hasStateClass = properties.Count > 0;

            if (hasStateClass)
            {
                foreach (var pair in properties)
                {
                    GenerateStateClassProperty(stateClass, asyncProperties[pair.Key], pair.Key, pair.Value);
                }

                var returnType = new CodeTypeReference("System.Collections.Generic.IDictionary",
                                                       new CodeTypeReference(typeof(string)), new CodeTypeReference(typeof(object)));
                var concreteType = new CodeTypeReference("System.Collections.Generic.Dictionary",
                                                         new CodeTypeReference(typeof(string)), new CodeTypeReference(typeof(object)));

                var asDictionary = new CodeMemberMethod
                {
                    Name       = "AsDictionary",
                    Attributes = MemberAttributes.Public | MemberAttributes.Override,
                    ReturnType = returnType
                };

                asDictionary.Statements.Add(new CodeVariableDeclarationStatement(concreteType, "result", new CodeObjectCreateExpression(concreteType)));
                foreach (var pair in properties)
                {
                    asDictionary.Statements.Add(new CodeAssignStatement(
                                                    new CodeIndexerExpression(new CodeVariableReferenceExpression("result"), new CodePrimitiveExpression(pair.Key)),
                                                    new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), pair.Key)));
                }

                asDictionary.Statements.Add(new CodeMethodReturnStatement(new CodeVariableReferenceExpression("result")));
                stateClass.Members.Add(asDictionary);

                GenerateSetAll(stateClass, properties);
                GenerateToString(stateClass, stateClassName, properties);
            }

            // Copier, serializer, and deserializer for the state class
            var copier       = SerializerGenerationUtilities.GenerateCopier("_Copier", stateClassName, genericTypeParams);
            var serializer   = SerializerGenerationUtilities.GenerateSerializer("_Serializer", stateClassName, genericTypeParams);
            var deserializer = SerializerGenerationUtilities.GenerateDeserializer("_Deserializer", stateClassName, genericTypeParams);

            var ctor = new CodeConstructor {
                Attributes = (copier.Attributes & ~MemberAttributes.AccessMask) | MemberAttributes.Public
            };

            ctor.BaseConstructorArgs.Add(new CodePrimitiveExpression(TypeUtils.GetFullName(grainInterfaceData.Type)));
            ctor.Statements.Add(new CodeMethodInvokeExpression(
                                    new CodeThisReferenceExpression(),
                                    "InitStateFields"));

            copier.Statements.Add(new CodeMethodReturnStatement(
                                      new CodeMethodInvokeExpression(new CodeVariableReferenceExpression("input"), "DeepCopy")));

            serializer.Statements.Add(
                new CodeMethodInvokeExpression(
                    new CodeVariableReferenceExpression("input"),
                    "SerializeTo", new CodeArgumentReferenceExpression("stream")));

            deserializer.Statements.Add(new CodeVariableDeclarationStatement(stateClassName, "result",
                                                                             new CodeObjectCreateExpression(stateClassName)));
            deserializer.Statements.Add(new CodeMethodInvokeExpression(
                                            new CodeVariableReferenceExpression("result"),
                                            "DeserializeFrom",
                                            new CodeArgumentReferenceExpression("stream")));
            deserializer.Statements.Add(new CodeMethodReturnStatement(
                                            new CodeVariableReferenceExpression("result")));

            stateClass.Members.Add(ctor);
            stateClass.Members.Add(initStateFields);
            stateClass.Members.Add(copier);
            stateClass.Members.Add(serializer);
            stateClass.Members.Add(deserializer);

            return(stateClass);
        }
Example #2
0
        protected override CodeTypeDeclaration GetStateClass(GrainInterfaceData grainInterfaceData, Action <Type> referred, string stateClassBaseName, string stateClassName, out bool hasStateClass)
        {
            var sourceType = grainInterfaceData.Type;

            stateClassName = FixupTypeName(stateClassName);
            CodeTypeParameterCollection genericTypeParams = grainInterfaceData.GenericTypeParams;
            Func <Type, bool>           nonamespace       = t => false;
            Type persistentInterface = GetPersistentInterface(sourceType);

            Dictionary <string, PropertyInfo> asyncProperties = GrainInterfaceData.GetPersistentProperties(persistentInterface)
                                                                .ToDictionary(p => p.Name.Substring(p.Name.LastIndexOf('.') + 1), p => p);

            Dictionary <string, string> properties = asyncProperties.ToDictionary(p => p.Key,
                                                                                  p => GetGenericTypeName(GrainInterfaceData.GetPromptType(p.Value.PropertyType), referred, nonamespace));

            hasStateClass = properties.Count > 0;

            if (!hasStateClass)
            {
                return(null);
            }

            var typeAccess = (persistentInterface != null && !persistentInterface.IsPublic) ? "internal" : "public";

            StartNewLine();
            StartNewLine();
            generatedCode.AppendFormat(@"[<System.CodeDom.Compiler.GeneratedCodeAttribute(""{0}"", ""{1}"")>]", CODE_GENERATOR_NAME, CodeGeneratorVersion);
            StartNewLine();
            generatedCode.AppendFormat(@"[<System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute()>]");
            StartNewLine();
            generatedCode.AppendFormat(@"[<System.SerializableAttribute()>]");
            StartNewLine();
            var grainName = grainInterfaceData.Type.Namespace + "." + TypeUtils.GetParameterizedTemplateName(grainInterfaceData.Type);

            generatedCode.AppendFormat(@"[<global.Orleans.CodeGeneration.GrainStateAttribute(""{0}"")>]", grainName);
            StartNewLine();
            generatedCode.AppendFormat(@"type {0} {1}", typeAccess, stateClassBaseName);

            if (genericTypeParams != null && genericTypeParams.Count > 0)
            {
                generatedCode.Append('<');
                for (int p = 0; p < genericTypeParams.Count; ++p)
                {
                    if (p > 0)
                    {
                        generatedCode.Append(',');
                    }

                    CodeTypeParameter param = genericTypeParams[p];
                    generatedCode.Append('\'').Append(param.Name);
                }
                generatedCode.Append('>');
            }

            generatedCode.AppendFormat(@"() =");
            IncreaseIndent();
            StartNewLine();
            generatedCode.AppendFormat(@"inherit global.Orleans.CodeGeneration.GrainState(""{0}"")", grainName);
            StartNewLine();

            var declaringTypes = new Dictionary <string, List <KeyValuePair <string, PropertyInfo> > >();

            foreach (var pair in asyncProperties)
            {
                var dtName = GetGenericTypeName(pair.Value.DeclaringType, referred, nonamespace);
                if (!declaringTypes.ContainsKey(dtName))
                {
                    declaringTypes.Add(dtName, new List <KeyValuePair <string, PropertyInfo> >());
                }

                var lst = declaringTypes[dtName];
                lst.Add(pair);
            }

            foreach (var declaringType in declaringTypes)
            {
                StartNewLine();
                generatedCode.AppendFormat(@"interface {0} with", declaringType.Key);

                IncreaseIndent();
                foreach (var pair in declaringType.Value)
                {
                    var propertyType = pair.Value.PropertyType;

                    bool noCreateNew = propertyType.IsPrimitive || typeof(string).IsAssignableFrom(propertyType) || // Primative types
                                       propertyType.IsAbstract || propertyType.IsInterface || propertyType.IsGenericParameter || // No concrete implementation
                                       propertyType.GetConstructor(Type.EmptyTypes) == null; // No default constructor

                    var initExpr = noCreateNew ?
                                   string.Format("Unchecked.defaultof<{0}>", GetGenericTypeName(propertyType, referred, nonamespace)) :
                                   string.Format("{0}()", GetGenericTypeName(propertyType, referred, nonamespace));

                    StartNewLine();
                    generatedCode.AppendFormat(@"override val {0} = {1} with get,set", pair.Key, initExpr);
                }
                DecreaseIndent();
            }

            GenerateSetAll(asyncProperties, referred);
            GenerateAsDictionary(asyncProperties, referred);
            GenerateToString(stateClassName, asyncProperties, referred);

            // Generate the serialization members.

            StartNewLine();
            StartNewLine();
            generatedCode.AppendFormat(@"[<global.Orleans.CodeGeneration.CopierMethodAttribute()>]");
            StartNewLine();
            generatedCode.AppendFormat(@"static member public _Copier(original:obj) : obj =");
            IncreaseIndent();
            StartNewLine();
            generatedCode.AppendFormat(@"let input = original :?> {0}", stateClassBaseName);
            StartNewLine();
            generatedCode.AppendFormat(@"input.DeepCopy() :> obj");
            DecreaseIndent();

            StartNewLine();
            StartNewLine();
            generatedCode.AppendFormat(@"[<global.Orleans.CodeGeneration.SerializerMethodAttribute()>]");
            StartNewLine();
            generatedCode.AppendFormat(@"static member public _Serializer(original:obj, stream:global.Orleans.Serialization.BinaryTokenStreamWriter, expected:System.Type) : unit =");
            IncreaseIndent();
            StartNewLine();
            generatedCode.AppendFormat(@"let input = original :?> {0}", stateClassBaseName);
            StartNewLine();
            generatedCode.AppendFormat(@"input.SerializeTo(stream)");
            DecreaseIndent();

            StartNewLine();
            StartNewLine();
            generatedCode.AppendFormat(@"[<global.Orleans.CodeGeneration.DeserializerMethodAttribute()>]");
            StartNewLine();
            generatedCode.AppendFormat(@"static member public _Deserializer(expected:System.Type, stream:global.Orleans.Serialization.BinaryTokenStreamReader) : obj =");
            IncreaseIndent();
            StartNewLine();
            generatedCode.AppendFormat(@"let result = {0}()", stateClassBaseName);
            StartNewLine();
            generatedCode.AppendFormat(@"result.DeserializeFrom(stream)");
            StartNewLine();
            generatedCode.AppendFormat(@"result :> obj");
            DecreaseIndent();

            DecreaseIndent();

            return(null);
        }