示例#1
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);
            }
        }
示例#2
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);
            }
        }
示例#3
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);
            }
        }
示例#4
0
        private static MemberDeclarationSyntax GenerateIsCompatibleMethod(Type grainType)
        {
            var method               = TypeUtils.Method((GrainReference _) => _.IsCompatible(default(int)));
            var methodDeclaration    = method.GetDeclarationSyntax();
            var interfaceIdParameter = method.GetParameters()[0].Name.ToIdentifierName();

            var interfaceIds =
                new HashSet <int>(
                    new[] { GrainInterfaceData.GetGrainInterfaceId(grainType) }.Concat(
                        GrainInterfaceData.GetRemoteInterfaces(grainType).Keys));

            var returnValue = default(BinaryExpressionSyntax);

            foreach (var interfaceId in interfaceIds)
            {
                var check = SF.BinaryExpression(
                    SyntaxKind.EqualsExpression,
                    interfaceIdParameter,
                    SF.LiteralExpression(SyntaxKind.NumericLiteralExpression, SF.Literal(interfaceId)));

                // If this is the first check, assign it, otherwise OR this check with the previous checks.
                returnValue = returnValue == null
                                  ? check
                                  : SF.BinaryExpression(SyntaxKind.LogicalOrExpression, returnValue, check);
            }

            return
                (methodDeclaration.AddBodyStatements(SF.ReturnStatement(returnValue))
                 .AddModifiers(SF.Token(SyntaxKind.OverrideKeyword)));
        }
示例#5
0
        private static GrainReferenceCaster MakeCaster(Type interfaceType)
        {
            CodeGeneratorManager.GenerateAndCacheCodeForAssembly(interfaceType.Assembly);
            var genericInterfaceType = interfaceType.IsConstructedGenericType
                                           ? interfaceType.GetGenericTypeDefinition()
                                           : interfaceType;

            // Try to find the correct GrainReference type for this interface.
            Type grainReferenceType;

            if (!GrainToReferenceMapping.TryGetValue(genericInterfaceType, out grainReferenceType))
            {
                throw new InvalidOperationException(
                          string.Format("Cannot find generated GrainReference class for interface '{0}'", interfaceType));
            }

            if (interfaceType.IsConstructedGenericType)
            {
                grainReferenceType = grainReferenceType.MakeGenericType(interfaceType.GenericTypeArguments);
            }

            // Get the grain reference constructor.
            var constructor =
                grainReferenceType.GetConstructors(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance)
                .Where(
                    _ =>
            {
                var parameters = _.GetParameters();
                return(parameters.Length == 1 && parameters[0].ParameterType == typeof(GrainReference));
            }).FirstOrDefault();

            if (constructor == null)
            {
                throw new InvalidOperationException(
                          string.Format(
                              "Cannot find suitable constructor on generated reference type for interface '{0}'",
                              interfaceType));
            }

            // Construct an expression to construct a new instance of this grain reference when given another grain
            // reference.
            var createLambdaParameter = Expression.Parameter(typeof(GrainReference), "gr");
            var createLambda          =
                Expression.Lambda <Func <GrainReference, IAddressable> >(
                    Expression.New(constructor, createLambdaParameter),
                    createLambdaParameter);
            var grainRefParameter = Expression.Parameter(typeof(IAddressable), "grainRef");
            var body =
                Expression.Call(
                    GrainReferenceCastInternalMethodInfo,
                    Expression.Constant(interfaceType),
                    createLambda,
                    grainRefParameter,
                    Expression.Constant(GrainInterfaceData.GetGrainInterfaceId(interfaceType)));

            // Compile and return the reference casting lambda.
            var lambda = Expression.Lambda <GrainReferenceCaster>(body, grainRefParameter);

            return(lambda.Compile());
        }
        /// <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         = GrainInterfaceData.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);
        }
示例#7
0
        /// <summary>
        /// Returns method declaration syntax for the InterfaceId property.
        /// </summary>
        /// <param name="grainType">The grain type.</param>
        /// <returns>Method declaration syntax for the InterfaceId property.</returns>
        private static MemberDeclarationSyntax GenerateInterfaceIdProperty(Type grainType)
        {
            var property    = TypeUtils.Member((IGrainMethodInvoker _) => _.InterfaceId);
            var returnValue = SF.LiteralExpression(
                SyntaxKind.NumericLiteralExpression,
                SF.Literal(GrainInterfaceData.GetGrainInterfaceId(grainType)));

            return
                (SF.PropertyDeclaration(typeof(int).GetTypeSyntax(), property.Name)
                 .AddAccessorListAccessors(
                     SF.AccessorDeclaration(SyntaxKind.GetAccessorDeclaration)
                     .AddBodyStatements(SF.ReturnStatement(returnValue)))
                 .AddModifiers(SF.Token(SyntaxKind.PublicKeyword)));
        }
示例#8
0
        /// <summary>
        /// Returns syntax for the options argument to <see cref="GrainReference.InvokeMethodAsync{T}"/> and <see cref="GrainReference.InvokeOneWayMethod"/>.
        /// </summary>
        /// <param name="method">The method which an invoke call is being generated for.</param>
        /// <returns>
        /// Argument syntax for the options argument to <see cref="GrainReference.InvokeMethodAsync{T}"/> and
        /// <see cref="GrainReference.InvokeOneWayMethod"/>, or <see langword="null"/> if no options are to be specified.
        /// </returns>
        private static ArgumentSyntax GetInvokeOptions(MethodInfo method)
        {
            var options = new List <ExpressionSyntax>();

            if (GrainInterfaceData.IsReadOnly(method))
            {
                options.Add(typeof(InvokeMethodOptions).GetNameSyntax().Member(InvokeMethodOptions.ReadOnly.ToString()));
            }

            if (GrainInterfaceData.IsUnordered(method))
            {
                options.Add(typeof(InvokeMethodOptions).GetNameSyntax().Member(InvokeMethodOptions.Unordered.ToString()));
            }

            if (GrainInterfaceData.IsAlwaysInterleave(method))
            {
                options.Add(typeof(InvokeMethodOptions).GetNameSyntax().Member(InvokeMethodOptions.AlwaysInterleave.ToString()));
            }

            ExpressionSyntax allOptions;

            if (options.Count <= 1)
            {
                allOptions = options.FirstOrDefault();
            }
            else
            {
                allOptions =
                    options.Aggregate((a, b) => SF.BinaryExpression(SyntaxKind.BitwiseOrExpression, a, b));
            }

            if (allOptions == null)
            {
                return(null);
            }

            return(SF.Argument(SF.NameColon("options"), SF.Token(SyntaxKind.None), allOptions));
        }
示例#9
0
        /// <summary>
        /// Generates invoker methods.
        /// </summary>
        /// <param name="grainType">The grain type.</param>
        /// <param name="onEncounteredType">
        /// The callback which is invoked when a type is encountered.
        /// </param>
        /// <returns>Invoker methods for the provided grain type.</returns>
        private static MemberDeclarationSyntax[] GenerateInvokeMethods(Type grainType, Action <Type> onEncounteredType)
        {
            var baseReference = SF.BaseExpression();
            var methods       = GrainInterfaceData.GetMethods(grainType);
            var members       = new List <MemberDeclarationSyntax>();

            foreach (var method in methods)
            {
                onEncounteredType(method.ReturnType);
                var methodId         = GrainInterfaceData.ComputeMethodId(method);
                var methodIdArgument =
                    SF.Argument(SF.LiteralExpression(SyntaxKind.NumericLiteralExpression, SF.Literal(methodId)));

                // Construct a new object array from all method arguments.
                var parameters = method.GetParameters();
                var body       = new List <StatementSyntax>();
                foreach (var parameter in parameters)
                {
                    onEncounteredType(parameter.ParameterType);
                    if (typeof(IGrainObserver).IsAssignableFrom(parameter.ParameterType))
                    {
                        body.Add(
                            SF.ExpressionStatement(
                                CheckGrainObserverParamInternalExpression.Invoke()
                                .AddArgumentListArguments(SF.Argument(parameter.Name.ToIdentifierName()))));
                    }
                }

                // Get the parameters argument value.
                ExpressionSyntax args;
                if (parameters.Length == 0)
                {
                    args = SF.LiteralExpression(SyntaxKind.NullLiteralExpression);
                }
                else
                {
                    args =
                        SF.ArrayCreationExpression(typeof(object).GetArrayTypeSyntax())
                        .WithInitializer(
                            SF.InitializerExpression(SyntaxKind.ArrayInitializerExpression)
                            .AddExpressions(parameters.Select(GetParameterForInvocation).ToArray()));
                }

                var options = GetInvokeOptions(method);

                // Construct the invocation call.
                if (method.ReturnType == typeof(void))
                {
                    var invocation = SF.InvocationExpression(baseReference.Member("InvokeOneWayMethod"))
                                     .AddArgumentListArguments(methodIdArgument)
                                     .AddArgumentListArguments(SF.Argument(args));

                    if (options != null)
                    {
                        invocation = invocation.AddArgumentListArguments(options);
                    }

                    body.Add(SF.ExpressionStatement(invocation));
                }
                else
                {
                    var returnType = method.ReturnType == typeof(Task)
                                         ? typeof(object)
                                         : method.ReturnType.GenericTypeArguments[0];
                    var invocation =
                        SF.InvocationExpression(baseReference.Member("InvokeMethodAsync", returnType))
                        .AddArgumentListArguments(methodIdArgument)
                        .AddArgumentListArguments(SF.Argument(args));

                    if (options != null)
                    {
                        invocation = invocation.AddArgumentListArguments(options);
                    }

                    body.Add(SF.ReturnStatement(invocation));
                }

                members.Add(method.GetDeclarationSyntax().AddBodyStatements(body.ToArray()));
            }

            return(members.ToArray());
        }
示例#10
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);
        }
 protected override string GetInvokerImpl(GrainInterfaceData si, CodeTypeDeclaration invokerClass, Type grainType, GrainInterfaceInfo grainInterfaceInfo, bool isClient)
 {
     throw new NotImplementedException("GetInvokerImpl");
 }
 protected override void AddCreateObjectReferenceMethods(GrainInterfaceData grainInterfaceData, CodeTypeDeclaration factoryClass)
 {
     throw new NotImplementedException("AddCreateObjectReferenceMethods");
 }
示例#13
0
 protected virtual void AddGetGrainMethods(GrainInterfaceData iface, CodeTypeDeclaration factoryClass)
 {
     throw new NotImplementedException("GrainNamespace.AddGetGrainMethods");
 }
示例#14
0
        protected override void AddGetGrainMethods(GrainInterfaceData iface, CodeTypeDeclaration factoryClass)
        {
            RecordReferencedNamespaceAndAssembly(typeof(GrainId));
            RecordReferencedNamespaceAndAssembly(iface.Type);
            var interfaceId   = GrainInterfaceData.GetGrainInterfaceId(iface.Type);
            var interfaceName = iface.InterfaceTypeName;

            Action <string> add = codeFmt =>
                                  factoryClass.Members.Add(new CodeSnippetTypeMember(
                                                               String.Format(codeFmt, FixupTypeName(interfaceName), interfaceId)));

            bool isGuidCompoundKey = typeof(IGrainWithGuidCompoundKey).IsAssignableFrom(iface.Type);
            bool isLongCompoundKey = typeof(IGrainWithIntegerCompoundKey).IsAssignableFrom(iface.Type);

            bool isGuidKey    = typeof(IGrainWithGuidKey).IsAssignableFrom(iface.Type);
            bool isLongKey    = typeof(IGrainWithIntegerKey).IsAssignableFrom(iface.Type);
            bool isStringKey  = typeof(IGrainWithStringKey).IsAssignableFrom(iface.Type);
            bool isDefaultKey = !(isGuidKey || isStringKey || isLongKey);

            if (isLongCompoundKey)
            {
                // the programmer has specified [ExtendedPrimaryKey] on the interface.
                add(
                    @"
                        Public Shared Function GetGrain(primaryKey as System.Int64, keyExt as System.String) As {0}
                            Return Cast(Global.Orleans.CodeGeneration.GrainFactoryBase.MakeKeyExtendedGrainReferenceInternal(GetType({0}), {1}, primaryKey, keyExt))
                        End Function");
                add(
                    @"
                        Public Shared Function GetGrain(primaryKey as System.Int64, keyExt as System.String, grainClassNamePrefix As System.String) As {0}
                            Return Cast(Global.Orleans.CodeGeneration.GrainFactoryBase.MakeKeyExtendedGrainReferenceInternal(GetType({0}), {1}, primaryKey, keyExt, grainClassNamePrefix))
                        End Function");
            }
            else if (isGuidCompoundKey)
            {
                add(
                    @"
                        Public Shared Function GetGrain(primaryKey As System.Guid, keyExt as System.String) As {0}
                            Return Cast(Global.Orleans.CodeGeneration.GrainFactoryBase.MakeKeyExtendedGrainReferenceInternal(GetType({0}), {1}, primaryKey, keyExt))
                        End Function");
                add(
                    @"
                        Public Shared Function GetGrain(primaryKey As System.Guid, keyExt as System.String, grainClassNamePrefix As System.String) As {0}
                            Return Cast(Global.Orleans.CodeGeneration.GrainFactoryBase.MakeKeyExtendedGrainReferenceInternal(GetType({0}), {1}, primaryKey, keyExt,grainClassNamePrefix))
                        End Function");
            }
            else
            {
                // the programmer has not specified [ExplicitPlacement] on the interface nor [ExtendedPrimaryKey].
                if (isLongKey || isDefaultKey)
                {
                    add(
                        @"
                        Public Shared Function GetGrain(primaryKey as System.Int64) As {0}
                            Return Cast(Global.Orleans.CodeGeneration.GrainFactoryBase.MakeGrainReferenceInternal(GetType({0}), {1}, primaryKey))
                        End Function");
                    add(
                        @"
                        Public Shared Function GetGrain(primaryKey as System.Int64, grainClassNamePrefix As System.String) As {0}
                            Return Cast(Global.Orleans.CodeGeneration.GrainFactoryBase.MakeGrainReferenceInternal(GetType({0}), {1}, primaryKey, grainClassNamePrefix))
                        End Function");
                }
                if (isGuidKey || isDefaultKey)
                {
                    add(
                        @"
                        Public Shared Function GetGrain(primaryKey As System.Guid) As {0}
                            Return Cast(Global.Orleans.CodeGeneration.GrainFactoryBase.MakeGrainReferenceInternal(GetType({0}), {1}, primaryKey))
                        End Function");
                    add(
                        @"
                        Public Shared Function GetGrain(primaryKey As System.Guid, grainClassNamePrefix As System.String) As {0}
                            Return Cast(Global.Orleans.CodeGeneration.GrainFactoryBase.MakeGrainReferenceInternal(GetType({0}), {1}, primaryKey, grainClassNamePrefix))
                        End Function");
                }
                if (isStringKey)
                {
                    add(
                        @"
                        Public Shared Function GetGrain(primaryKey As System.String) As {0}
                            Return Cast(Global.Orleans.CodeGeneration.GrainFactoryBase.MakeGrainReferenceInternal(GetType({0}), {1}, primaryKey))
                        End Function");
                    add(
                        @"
                        Public Shared Function GetGrain(primaryKey As System.String, grainClassNamePrefix As System.String) As {0}
                            Return Cast(Global.Orleans.CodeGeneration.GrainFactoryBase.MakeGrainReferenceInternal(GetType({0}), {1}, primaryKey, grainClassNamePrefix))
                        End Function");
                }
            }
        }
示例#15
0
        /// <summary>
        /// Generates a syntax tree for the provided assemblies.
        /// </summary>
        /// <param name="assemblies">The assemblies to generate code for.</param>
        /// <param name="runtime">Whether or not runtime code generation is being performed.</param>
        /// <returns>The generated syntax tree.</returns>
        private static GeneratedSyntax GenerateForAssemblies(List <Assembly> assemblies, bool runtime)
        {
            if (Logger.IsVerbose)
            {
                Logger.Verbose(
                    "Generating code for assemblies: {0}",
                    string.Join(", ", assemblies.Select(_ => _.FullName)));
            }

            Assembly       targetAssembly;
            HashSet <Type> ignoredTypes;

            if (runtime)
            {
                // Ignore types which have already been accounted for.
                ignoredTypes   = GetTypesWithGeneratedSupportClasses();
                targetAssembly = null;
            }
            else
            {
                ignoredTypes   = new HashSet <Type>();
                targetAssembly = assemblies.FirstOrDefault();
            }

            var members = new List <MemberDeclarationSyntax>();

            // If any KnownAssemblies have been specified, include them during code generation.
            var knownAssemblies =
                assemblies.SelectMany(_ => _.GetCustomAttributes <KnownAssemblyAttribute>())
                .Select(_ => _.Assembly)
                .Distinct()
                .ToSet();

            if (knownAssemblies.Count > 0)
            {
                knownAssemblies.UnionWith(assemblies);
                assemblies = knownAssemblies.ToList();
            }

            // Get types from assemblies which reference Orleans and are not generated assemblies.
            var includedTypes = new HashSet <Type>();

            for (var i = 0; i < assemblies.Count; i++)
            {
                var assembly = assemblies[i];
                foreach (var attribute in assembly.GetCustomAttributes <KnownTypeAttribute>())
                {
                    ConsiderType(attribute.Type, runtime, targetAssembly, includedTypes);
                }

                foreach (var type in assembly.DefinedTypes)
                {
                    ConsiderType(type, runtime, targetAssembly, includedTypes);
                }
            }

            includedTypes.RemoveWhere(_ => ignoredTypes.Contains(_));

            // Group the types by namespace and generate the required code in each namespace.
            foreach (var group in includedTypes.GroupBy(_ => CodeGeneratorCommon.GetGeneratedNamespace(_)))
            {
                var namespaceMembers = new List <MemberDeclarationSyntax>();
                foreach (var type in group)
                {
                    // The module containing the serializer.
                    var module = runtime ? null : type.Module;

                    // Every type which is encountered must be considered for serialization.
                    Action <Type> onEncounteredType = encounteredType =>
                    {
                        // If a type was encountered which can be accessed, process it for serialization.
                        SerializerGenerationManager.RecordTypeToGenerate(encounteredType, module, targetAssembly);
                    };

                    if (Logger.IsVerbose2)
                    {
                        Logger.Verbose2("Generating code for: {0}", type.GetParseableName());
                    }

                    if (GrainInterfaceData.IsGrainInterface(type))
                    {
                        if (Logger.IsVerbose2)
                        {
                            Logger.Verbose2(
                                "Generating GrainReference and MethodInvoker for {0}",
                                type.GetParseableName());
                        }

                        GrainInterfaceData.ValidateInterfaceRules(type);

                        namespaceMembers.Add(GrainReferenceGenerator.GenerateClass(type, onEncounteredType));
                        namespaceMembers.Add(GrainMethodInvokerGenerator.GenerateClass(type));
                    }

                    // Generate serializers.
                    var  first = true;
                    Type toGen;
                    while (SerializerGenerationManager.GetNextTypeToProcess(out toGen))
                    {
                        if (!runtime)
                        {
                            if (first)
                            {
                                ConsoleText.WriteStatus("ClientGenerator - Generating serializer classes for types:");
                                first = false;
                            }

                            ConsoleText.WriteStatus(
                                "\ttype " + toGen.FullName + " in namespace " + toGen.Namespace
                                + " defined in Assembly " + toGen.Assembly.GetName());
                        }

                        if (Logger.IsVerbose2)
                        {
                            Logger.Verbose2(
                                "Generating & Registering Serializer for Type {0}",
                                toGen.GetParseableName());
                        }

                        namespaceMembers.AddRange(SerializerGenerator.GenerateClass(toGen, onEncounteredType));
                    }
                }

                if (namespaceMembers.Count == 0)
                {
                    if (Logger.IsVerbose)
                    {
                        Logger.Verbose2("Skipping namespace: {0}", group.Key);
                    }

                    continue;
                }

                members.Add(
                    SF.NamespaceDeclaration(SF.ParseName(group.Key))
                    .AddUsings(
                        TypeUtils.GetNamespaces(typeof(TaskUtility), typeof(GrainExtensions))
                        .Select(_ => SF.UsingDirective(SF.ParseName(_)))
                        .ToArray())
                    .AddMembers(namespaceMembers.ToArray()));
            }

            return(new GeneratedSyntax
            {
                SourceAssemblies = assemblies,
                Syntax = members.Count > 0 ? SF.CompilationUnit().AddMembers(members.ToArray()) : null
            });
        }
示例#16
0
        internal void AddReferenceClass(GrainInterfaceData interfaceData)
        {
            bool isObserver = IsObserver(interfaceData.Type);
            CodeTypeParameterCollection genericTypeParam = interfaceData.GenericTypeParams;

            // Declare factory class
            var factoryClass = new CodeTypeDeclaration(interfaceData.FactoryClassBaseName);

            if (genericTypeParam != null)
            {
                factoryClass.TypeParameters.AddRange(genericTypeParam);
            }

            factoryClass.IsClass        = true;
            factoryClass.TypeAttributes = interfaceData.Type.IsPublic ? TypeAttributes.Public : TypeAttributes.NotPublic;
            MarkAsGeneratedCode(factoryClass);
            AddFactoryMethods(interfaceData, factoryClass);
            AddCastMethods(interfaceData, true, factoryClass);

            if (ShouldGenerateObjectRefFactory(interfaceData))
            {
                AddCreateObjectReferenceMethods(interfaceData, factoryClass);
            }

            int factoryClassIndex = ReferencedNamespace.Types.Add(factoryClass);

            var referenceClass = new CodeTypeDeclaration(interfaceData.ReferenceClassBaseName);

            if (genericTypeParam != null)
            {
                referenceClass.TypeParameters.AddRange(genericTypeParam);
            }
            referenceClass.IsClass = true;

            referenceClass.BaseTypes.Add(new CodeTypeReference(typeof(GrainReference), CodeTypeReferenceOptions.GlobalReference));
            referenceClass.BaseTypes.Add(new CodeTypeReference(typeof(IAddressable), CodeTypeReferenceOptions.GlobalReference));
            var tref = new CodeTypeReference(interfaceData.Type);

            if (genericTypeParam != null)
            {
                foreach (CodeTypeParameter tp in genericTypeParam)
                {
                    tref.TypeArguments.Add(tp.Name);
                }
            }

            referenceClass.BaseTypes.Add(tref);

            MarkAsGeneratedCode(referenceClass);
            referenceClass.TypeAttributes = TypeAttributes.NestedAssembly;
            referenceClass.CustomAttributes.Add(
                new CodeAttributeDeclaration(new CodeTypeReference(typeof(SerializableAttribute))));

            referenceClass.CustomAttributes.Add(
                new CodeAttributeDeclaration(
                    new CodeTypeReference(typeof(GrainReferenceAttribute), CodeTypeReferenceOptions.GlobalReference),
                    new CodeAttributeArgument(
                        new CodePrimitiveExpression(interfaceData.Type.Namespace + "." + TypeUtils.GetParameterizedTemplateName((interfaceData.Type))))));

            var baseReferenceConstructor2 = new CodeConstructor {
                Attributes = MemberAttributes.FamilyOrAssembly
            };

            baseReferenceConstructor2.Parameters.Add(new CodeParameterDeclarationExpression(
                                                         new CodeTypeReference(typeof(GrainReference), CodeTypeReferenceOptions.GlobalReference), "reference"));

            baseReferenceConstructor2.BaseConstructorArgs.Add(new CodeVariableReferenceExpression("reference"));
            referenceClass.Members.Add(baseReferenceConstructor2);

            var baseReferenceConstructor3 = new CodeConstructor {
                Attributes = MemberAttributes.FamilyOrAssembly
            };

            baseReferenceConstructor3.Parameters.Add(new CodeParameterDeclarationExpression("SerializationInfo", "info"));
            baseReferenceConstructor3.BaseConstructorArgs.Add(new CodeVariableReferenceExpression("info"));
            baseReferenceConstructor3.Parameters.Add(new CodeParameterDeclarationExpression("StreamingContext", "context"));
            baseReferenceConstructor3.BaseConstructorArgs.Add(new CodeVariableReferenceExpression("context"));
            referenceClass.Members.Add(baseReferenceConstructor3);

            var grainRef     = new CodeTypeReference(typeof(GrainReference), CodeTypeReferenceOptions.GlobalReference);
            var refClassName = FixupTypeName(interfaceData.ReferenceClassName);

            // Copier, serializer, and deserializer for this type
            var copier = SerializerGenerationUtilities.GenerateCopier("_Copier", refClassName, genericTypeParam);

            copier.Statements.Add(
                new CodeMethodReturnStatement(
                    new CodeCastExpression(refClassName,
                                           new CodeMethodInvokeExpression(new CodeTypeReferenceExpression(grainRef), "CopyGrainReference", new CodeVariableReferenceExpression("input")))));
            referenceClass.Members.Add(copier);

            var serializer = SerializerGenerationUtilities.GenerateSerializer("_Serializer", refClassName, genericTypeParam);

            serializer.Statements.Add(
                new CodeMethodInvokeExpression(
                    new CodeTypeReferenceExpression(grainRef),
                    "SerializeGrainReference", new CodeVariableReferenceExpression("input"),
                    new CodeArgumentReferenceExpression("stream"),
                    new CodeArgumentReferenceExpression("expected")));
            referenceClass.Members.Add(serializer);

            var deserializer = SerializerGenerationUtilities.GenerateDeserializer("_Deserializer", refClassName, genericTypeParam);

            deserializer.Statements.Add(
                new CodeMethodReturnStatement(
                    new CodeMethodInvokeExpression(
                        new CodeTypeReferenceExpression(refClassName),
                        "Cast",
                        new CodeCastExpression(grainRef,
                                               new CodeMethodInvokeExpression(
                                                   new CodeTypeReferenceExpression(grainRef),
                                                   "DeserializeGrainReference",
                                                   new CodeArgumentReferenceExpression("expected"), new CodeArgumentReferenceExpression("stream"))))));
            referenceClass.Members.Add(deserializer);

            // this private class is the "implementation class" for the interface reference type
            ReferencedNamespace.Types[factoryClassIndex].Members.Add(referenceClass);

            AddCastMethods(interfaceData, false, referenceClass);

            var interfaceId       = GrainInterfaceData.GetGrainInterfaceId(interfaceData.Type);
            var interfaceIdMethod = new CodeMemberProperty
            {
                Name       = "InterfaceId",
                Type       = new CodeTypeReference(typeof(int)),
                Attributes = MemberAttributes.Family | MemberAttributes.Override,
                HasSet     = false,
                HasGet     = true
            };

            interfaceIdMethod.GetStatements.Add(new CodeMethodReturnStatement(new CodePrimitiveExpression(interfaceId)));
            referenceClass.Members.Add(interfaceIdMethod);


            var left = new CodeBinaryOperatorExpression(
                new CodeArgumentReferenceExpression("interfaceId"),
                CodeBinaryOperatorType.ValueEquality,
                new CodePropertyReferenceExpression(new CodeThisReferenceExpression(), "InterfaceId"));

            var interfaceList = GrainInterfaceData.GetRemoteInterfaces(interfaceData.Type);

            foreach (int iid in interfaceList.Keys)
            {
                if (iid == interfaceId)
                {
                    continue;                     // already covered the main interfaces
                }
                left = new CodeBinaryOperatorExpression(
                    left,
                    CodeBinaryOperatorType.BooleanOr,
                    new CodeBinaryOperatorExpression(
                        new CodeArgumentReferenceExpression("interfaceId"),
                        CodeBinaryOperatorType.ValueEquality,
                        new CodePrimitiveExpression(iid)));
            }

            var interfaceIsCompatibleMethod = new CodeMemberMethod
            {
                Name       = "IsCompatible",
                ReturnType = new CodeTypeReference(typeof(bool))
            };

            interfaceIsCompatibleMethod.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(int)), "interfaceId"));
            interfaceIsCompatibleMethod.Attributes = MemberAttributes.Public | MemberAttributes.Override;
            interfaceIsCompatibleMethod.Statements.Add(new CodeMethodReturnStatement(left));
            referenceClass.Members.Add(interfaceIsCompatibleMethod);

            var interfaceNameMethod = new CodeMemberProperty
            {
                Name       = "InterfaceName",
                Type       = new CodeTypeReference(typeof(string)),
                Attributes = MemberAttributes.Family | MemberAttributes.Override,
                HasSet     = false,
                HasGet     = true
            };

            interfaceNameMethod.GetStatements.Add(new CodeMethodReturnStatement(new CodePrimitiveExpression(FixupTypeName(interfaceData.TypeFullName))));
            referenceClass.Members.Add(interfaceNameMethod);

            var invokerClassName = interfaceData.InvokerClassName;

            var getMethodNameMethod = new CodeMemberMethod
            {
                Name       = "GetMethodName",
                ReturnType = new CodeTypeReference(typeof(string))
            };

            getMethodNameMethod.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(int)), "interfaceId"));
            getMethodNameMethod.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(int)), "methodId"));
            getMethodNameMethod.Attributes = MemberAttributes.Family | MemberAttributes.Override;
            var methodInvokerName = string.Format("{0}.GetMethodName", FixupTypeName(invokerClassName));

            getMethodNameMethod.Statements.Add(
                new CodeMethodReturnStatement(
                    new CodeMethodInvokeExpression(
                        null, methodInvokerName,
                        new CodeArgumentReferenceExpression("interfaceId"),
                        new CodeArgumentReferenceExpression("methodId"))));
            referenceClass.Members.Add(getMethodNameMethod);

            CodeTypeDeclaration invokerClass = GetInvokerClass(interfaceData, true);

            invokerClass.TypeAttributes = TypeAttributes.NotPublic;
            ReferencedNamespace.Types.Add(invokerClass);

            ReferencedNamespace.Imports.Add(new CodeNamespaceImport("System"));
            ReferencedNamespace.Imports.Add(new CodeNamespaceImport("System.Net"));
            ReferencedNamespace.Imports.Add(new CodeNamespaceImport("System.Runtime.Serialization"));
            ReferencedNamespace.Imports.Add(new CodeNamespaceImport("System.Runtime.Serialization.Formatters.Binary"));
            ReferencedNamespace.Imports.Add(new CodeNamespaceImport("System.IO"));
            ReferencedNamespace.Imports.Add(new CodeNamespaceImport("System.Collections.Generic"));

            MethodInfo[] methods = GrainInterfaceData.GetMethods(interfaceData.Type);
            AddMethods(methods, referenceClass, genericTypeParam, isObserver);
        }
示例#17
0
        private string GetMethodDispatchSwitchForInterface(int interfaceId, InterfaceInfo interfaceInfo)
        {
            var methodSwitchBody = String.Empty;

            foreach (int methodId in interfaceInfo.Methods.Keys)
            {
                var methodInfo = interfaceInfo.Methods[methodId];
                var returnType = methodInfo.ReturnType;
                GetGenericTypeName(returnType); // Adds return type assembly and namespace to import / library lists if necessary
                var invokeGrainArgs = string.Empty;

                ParameterInfo[] paramInfoArray = methodInfo.GetParameters();
                for (int count = 0; count < paramInfoArray.Length; count++)
                {
                    invokeGrainArgs += string.Format("CType(arguments({1}),{0})",
                                                     GetGenericTypeName(paramInfoArray[count].ParameterType), count);
                    if (count < paramInfoArray.Length - 1)
                    {
                        invokeGrainArgs += ", ";
                    }
                }

                // todo: parameters for indexed properties
                var grainTypeName = GetGenericTypeName(interfaceInfo.InterfaceType);
                var methodName    = methodInfo.Name;

                string invokeGrainMethod;
                if (!methodInfo.IsSpecialName)
                {
                    invokeGrainMethod = string.Format("CType(grain,{0}).{1}({2})", grainTypeName, methodName, invokeGrainArgs);
                }
                else if (methodInfo.Name.StartsWith("get_"))
                {
                    invokeGrainMethod = string.Format("CType(grain,{0}).{1}", grainTypeName, methodName.Substring(4));
                }
                else if (methodInfo.Name.StartsWith("set_"))
                {
                    invokeGrainMethod = string.Format("CType(grain,{0}).{1} = {2}", grainTypeName, methodName.Substring(4), invokeGrainArgs);
                }
                else
                {
                    // Should never happen
                    throw new InvalidOperationException("Don't know how to handle method " + methodInfo);
                }

                string caseBodyStatements;
                if (returnType == typeof(void))
                {
                    caseBodyStatements = string.Format(
                        @"{0}
Return System.Threading.Tasks.Task.FromResult(CObj(True))
",
                        invokeGrainMethod);
                }
                else if (GrainInterfaceData.IsTaskType(returnType))
                {
                    if (returnType == typeof(Task))
                    {
                        caseBodyStatements = string.Format(
                            @"    Return {0}.ContinueWith(Function(t)                                    
                                    If t.Status = System.Threading.Tasks.TaskStatus.Faulted Then : Throw t.Exception : End If
                                    Return Nothing
                                End Function)
",
                            invokeGrainMethod);
                    }
                    else
                    {
                        caseBodyStatements = string.Format(
                            @"Return {0}.ContinueWith(Function(t) CObj(t.Result))
",
                            invokeGrainMethod);
                    }
                }
                else
                {
                    // Should never happen
                    throw new InvalidOperationException(string.Format(
                                                            "Don't know how to create invoker for method {0} with Id={1} of returnType={2}", methodInfo, methodId, returnType));
                }

                methodSwitchBody += string.Format(@"                            Case {0} 
                                {1}", methodId, caseBodyStatements);
            }

            var defaultCase = @"                            Case Else 
                            Throw New NotImplementedException(""interfaceId=""+interfaceId+"",methodId=""+methodId)";

            return(String.Format(@"Case {0}  ' {1}
                        Select Case methodId
{2}                            
{3}
                        End Select
",
                                 interfaceId, interfaceInfo.InterfaceType.Name, methodSwitchBody, defaultCase));
        }
示例#18
0
        private CodeTypeDeclaration GetInvokerClass(GrainInterfaceData si, bool isClient)
        {
            Type grainType = si.Type;
            CodeTypeParameterCollection genericTypeParams = si.GenericTypeParams;

            var invokerClass = new CodeTypeDeclaration(si.InvokerClassBaseName);

            if (genericTypeParams != null)
            {
                invokerClass.TypeParameters.AddRange(genericTypeParams);
            }

            invokerClass.IsClass = true;
            MarkAsGeneratedCode(invokerClass);
            invokerClass.BaseTypes.Add(si.IsExtension
                ? new CodeTypeReference(typeof(IGrainExtensionMethodInvoker), CodeTypeReferenceOptions.GlobalReference)
                : new CodeTypeReference(typeof(IGrainMethodInvoker), CodeTypeReferenceOptions.GlobalReference));

            GrainInterfaceInfo grainInterfaceInfo = GetInterfaceInfo(grainType);
            var interfaceId = grainInterfaceInfo.Interfaces.Keys.First();

            invokerClass.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeTypeReference(typeof(MethodInvokerAttribute), CodeTypeReferenceOptions.GlobalReference),
                                                                           new CodeAttributeArgument(new CodePrimitiveExpression(grainType.Namespace + "." + TypeUtils.GetParameterizedTemplateName(grainType))),
                                                                           new CodeAttributeArgument(new CodePrimitiveExpression(interfaceId))));

            var interfaceIdProperty = new CodeMemberProperty
            {
                Name       = "InterfaceId",
                Attributes = MemberAttributes.Public | MemberAttributes.Final,
                Type       = new CodeTypeReference(typeof(int))
            };

            interfaceIdProperty.GetStatements.Add(new CodeMethodReturnStatement(new CodePrimitiveExpression(interfaceId)));
            interfaceIdProperty.PrivateImplementationType = new CodeTypeReference(typeof(IGrainMethodInvoker), CodeTypeReferenceOptions.GlobalReference);
            invokerClass.Members.Add(interfaceIdProperty);

            //Add invoke method for Orleans message
            var orleansInvoker = new CodeMemberMethod
            {
                Attributes = MemberAttributes.Public | MemberAttributes.Final,
                Name       = "Invoke",
                ReturnType = new CodeTypeReference(typeof(Task <object>), CodeTypeReferenceOptions.GlobalReference)
            };

            orleansInvoker.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(IAddressable), CodeTypeReferenceOptions.GlobalReference), "grain"));
            orleansInvoker.Parameters.Add(new CodeParameterDeclarationExpression(typeof(int), "interfaceId"));
            orleansInvoker.Parameters.Add(new CodeParameterDeclarationExpression(typeof(int), "methodId"));
            orleansInvoker.Parameters.Add(new CodeParameterDeclarationExpression(typeof(object[]), "arguments"));
            orleansInvoker.PrivateImplementationType = new CodeTypeReference(typeof(IGrainMethodInvoker), CodeTypeReferenceOptions.GlobalReference);

            var orleansInvokerImpl = new CodeSnippetStatement(GetInvokerImpl(si, invokerClass, grainType, grainInterfaceInfo, isClient));

            orleansInvoker.Statements.Add(orleansInvokerImpl);
            invokerClass.Members.Add(orleansInvoker);

            //Add TryInvoke method for Orleans message, if the type is an extension interface
            if (si.IsExtension)
            {
                var orleansTryInvoker = new CodeMemberMethod
                {
                    Attributes = MemberAttributes.Public | MemberAttributes.Final,
                    Name       = "Invoke",
                    ReturnType = new CodeTypeReference(typeof(Task <object>), CodeTypeReferenceOptions.GlobalReference)
                };
                orleansTryInvoker.Parameters.Add(new CodeParameterDeclarationExpression(new CodeTypeReference(typeof(IGrainExtension), CodeTypeReferenceOptions.GlobalReference), "grain"));
                orleansTryInvoker.Parameters.Add(new CodeParameterDeclarationExpression(typeof(int), "interfaceId"));
                orleansTryInvoker.Parameters.Add(new CodeParameterDeclarationExpression(typeof(int), "methodId"));
                orleansTryInvoker.Parameters.Add(new CodeParameterDeclarationExpression(typeof(object[]), "arguments"));
                orleansTryInvoker.PrivateImplementationType = new CodeTypeReference(typeof(IGrainExtensionMethodInvoker), CodeTypeReferenceOptions.GlobalReference);

                var orleansTryInvokerImp = new CodeSnippetStatement(GetInvokerImpl(si, invokerClass, grainType, grainInterfaceInfo, isClient));
                orleansTryInvoker.Statements.Add(orleansTryInvokerImp);
                invokerClass.Members.Add(orleansTryInvoker);
            }

            //Add GetMethodName() method
            var getMethodName = new CodeMemberMethod
            {
                Attributes = MemberAttributes.Public | MemberAttributes.Final | MemberAttributes.Static,
                Name       = "GetMethodName",
                ReturnType = new CodeTypeReference(typeof(string))
            };

            getMethodName.Parameters.Add(new CodeParameterDeclarationExpression(typeof(int), "interfaceId"));
            getMethodName.Parameters.Add(new CodeParameterDeclarationExpression(typeof(int), "methodId"));

            var orleansGetMethodNameImpl = new CodeSnippetStatement(GetOrleansGetMethodNameImpl(grainType, grainInterfaceInfo));

            getMethodName.Statements.Add(orleansGetMethodNameImpl);
            invokerClass.Members.Add(getMethodName);
            return(invokerClass);
        }
示例#19
0
 internal void AddStateClass(GrainInterfaceData interfaceData)
 {
     GetActivationNamespace(ReferencedNamespace, interfaceData);
 }
示例#20
0
 /// <summary>
 /// Generate Cast method in CodeDom and add it in reference class
 /// </summary>
 /// <param name="si">The service interface this grain reference type is being generated for</param>
 /// <param name="isFactory">whether the class being generated is a factory class rather than a grainref implementation</param>
 /// <param name="referenceClass">The class being generated for this grain reference type</param>
 protected virtual void AddCastMethods(GrainInterfaceData si, bool isFactory, CodeTypeDeclaration referenceClass)
 {
     throw new NotImplementedException("GrainNamespace.AddCastMethods");
 }
示例#21
0
 /// <summary>
 /// Generate Cast method in CodeDom and add it in reference class
 /// </summary>
 /// <param name="si">The service interface this grain reference type is being generated for</param>
 /// <param name="isFactory">whether the class being generated is a factory class rather than a grainref implementation</param>
 /// <param name="referenceClass">The class being generated for this grain reference type</param>
 protected override void AddCastMethods(GrainInterfaceData si, bool isFactory, CodeTypeDeclaration referenceClass)
 {
     throw new NotImplementedException("AddCastMethods");
 }
示例#22
0
 protected override void AddGetGrainMethods(GrainInterfaceData iface, CodeTypeDeclaration factoryClass)
 {
     throw new NotImplementedException("AddGetGrainMethods");
 }
示例#23
0
        internal static void RecordTypeToGenerate(Type t)
        {
            var typeInfo = t.GetTypeInfo();

            if (typeInfo.IsGenericParameter || ProcessedTypes.Contains(t) || TypesToProcess.Contains(t) ||
                typeof(Exception).GetTypeInfo().IsAssignableFrom(t))
            {
                return;
            }

            if (typeInfo.IsArray)
            {
                RecordTypeToGenerate(typeInfo.GetElementType());
                return;
            }

            if (typeInfo.IsNestedPublic || 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);
            }

            if (typeInfo.IsGenericType)
            {
                var args = t.GetGenericArguments();
                foreach (var arg in args)
                {
                    if (!arg.IsGenericParameter)
                    {
                        RecordTypeToGenerate(arg);
                    }
                }
            }

            if (typeInfo.IsInterface || typeInfo.IsAbstract || typeInfo.IsEnum || t == typeof(object) || t == typeof(void) ||
                GrainInterfaceData.IsTaskType(t))
            {
                return;
            }

            if (typeInfo.IsGenericType)
            {
                var def = typeInfo.GetGenericTypeDefinition();
                if (def == typeof(Task <>) || (SerializationManager.GetSerializer(def) != null) ||
                    ProcessedTypes.Contains(def) || typeof(IAddressable).IsAssignableFrom(def))
                {
                    return;
                }

                if (def.Namespace != null && (def.Namespace.Equals("System") || def.Namespace.StartsWith("System.")))
                {
                    Log.Warn(
                        ErrorCode.CodeGenSystemTypeRequiresSerializer,
                        "System type " + def.Name + " requires a serializer.");
                }
                else
                {
                    TypesToProcess.Add(def);
                }

                return;
            }

            if (typeInfo.IsOrleansPrimitive() || (SerializationManager.GetSerializer(t) != null) ||
                typeof(IAddressable).GetTypeInfo().IsAssignableFrom(t))
            {
                return;
            }

            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 asking the Orleans team to build a custom serializer for it.";
                Log.Warn(ErrorCode.CodeGenSystemTypeRequiresSerializer, message);
                return;
            }

            bool hasCopier       = false;
            bool hasSerializer   = false;
            bool hasDeserializer = false;

            foreach (var method in t.GetMethods(BindingFlags.Static | BindingFlags.Public))
            {
                if (method.GetCustomAttributes(typeof(SerializerMethodAttribute), false).Length > 0)
                {
                    hasSerializer = true;
                }
                else if (method.GetCustomAttributes(typeof(DeserializerMethodAttribute), false).Length > 0)
                {
                    hasDeserializer = true;
                }

                if (method.GetCustomAttributes(typeof(CopierMethodAttribute), false).Length > 0)
                {
                    hasCopier = true;
                }
            }

            if (hasCopier && hasSerializer && hasDeserializer)
            {
                return;
            }

            TypesToProcess.Add(t);
        }
        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);
        }
示例#25
0
        /// <summary>
        /// Generates a syntax tree for the provided assemblies.
        /// </summary>
        /// <param name="assemblies">The assemblies to generate code for.</param>
        /// <param name="runtime">Whether or not runtime code generation is being performed.</param>
        /// <returns>The generated syntax tree.</returns>
        private static GeneratedSyntax GenerateForAssemblies(List <Assembly> assemblies, bool runtime)
        {
            if (Logger.IsVerbose)
            {
                Logger.Verbose(
                    "Generating code for assemblies: {0}",
                    string.Join(", ", assemblies.Select(_ => _.FullName)));
            }

            Assembly       targetAssembly;
            HashSet <Type> ignoredTypes;

            if (runtime)
            {
                // Ignore types which have already been accounted for.
                ignoredTypes = CodeGeneratorCommon.GetTypesWithImplementations(
                    typeof(MethodInvokerAttribute),
                    typeof(GrainReferenceAttribute),
                    typeof(GrainStateAttribute),
                    typeof(SerializerAttribute));
                targetAssembly = null;
            }
            else
            {
                ignoredTypes   = new HashSet <Type>();
                targetAssembly = assemblies.FirstOrDefault();
            }

            var members = new List <MemberDeclarationSyntax>();

            // Get types from assemblies which reference Orleans and are not generated assemblies.
            var includedTypes = new HashSet <Type>();

            foreach (var type in assemblies.SelectMany(_ => _.GetTypes()))
            {
                // The module containing the serializer.
                var module = runtime ? null : type.Module;

                // Every type which is encountered must be considered for serialization.
                if (!type.IsNested && !type.IsGenericParameter && type.IsSerializable)
                {
                    // If a type was encountered which can be accessed, process it for serialization.
                    var isAccessibleForSerialization =
                        !TypeUtilities.IsTypeIsInaccessibleForSerialization(type, module, targetAssembly);
                    if (isAccessibleForSerialization)
                    {
                        includedTypes.Add(type);
                        SerializerGenerationManager.RecordTypeToGenerate(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);
                }
            }

            includedTypes.RemoveWhere(_ => ignoredTypes.Contains(_));

            // Group the types by namespace and generate the required code in each namespace.
            foreach (var group in includedTypes.GroupBy(_ => CodeGeneratorCommon.GetGeneratedNamespace(_)))
            {
                var namespaceMembers = new List <MemberDeclarationSyntax>();
                foreach (var type in group)
                {
                    // The module containing the serializer.
                    var module = runtime ? null : type.Module;

                    // Every type which is encountered must be considered for serialization.
                    Action <Type> onEncounteredType = encounteredType =>
                    {
                        // If a type was encountered which can be accessed, process it for serialization.
                        var isAccessibleForSerialization =
                            !TypeUtilities.IsTypeIsInaccessibleForSerialization(encounteredType, module, targetAssembly);
                        if (isAccessibleForSerialization)
                        {
                            SerializerGenerationManager.RecordTypeToGenerate(encounteredType);
                        }
                    };

                    if (Logger.IsVerbose2)
                    {
                        Logger.Verbose2("Generating code for: {0}", type.GetParseableName());
                    }

                    if (GrainInterfaceData.IsGrainInterface(type))
                    {
                        if (Logger.IsVerbose2)
                        {
                            Logger.Verbose2(
                                "Generating GrainReference and MethodInvoker for {0}",
                                type.GetParseableName());
                        }

                        namespaceMembers.Add(GrainReferenceGenerator.GenerateClass(type, onEncounteredType));
                        namespaceMembers.Add(GrainMethodInvokerGenerator.GenerateClass(type));
                    }

                    // Generate serializers.
                    var  first = true;
                    Type toGen;
                    while (SerializerGenerationManager.GetNextTypeToProcess(out toGen))
                    {
                        // Filter types which are inaccessible by the serialzation module/assembly.
                        var skipSerialzerGeneration =
                            toGen.GetAllFields()
                            .Any(
                                field =>
                                TypeUtilities.IsTypeIsInaccessibleForSerialization(
                                    field.FieldType,
                                    module,
                                    targetAssembly));
                        if (skipSerialzerGeneration)
                        {
                            continue;
                        }

                        if (!runtime)
                        {
                            if (first)
                            {
                                ConsoleText.WriteStatus("ClientGenerator - Generating serializer classes for types:");
                                first = false;
                            }

                            ConsoleText.WriteStatus(
                                "\ttype " + toGen.FullName + " in namespace " + toGen.Namespace
                                + " defined in Assembly " + toGen.Assembly.GetName());
                        }

                        if (Logger.IsVerbose2)
                        {
                            Logger.Verbose2(
                                "Generating & Registering Serializer for Type {0}",
                                toGen.GetParseableName());
                        }

                        namespaceMembers.AddRange(SerializerGenerator.GenerateClass(toGen, onEncounteredType));
                    }
                }

                if (namespaceMembers.Count == 0)
                {
                    if (Logger.IsVerbose)
                    {
                        Logger.Verbose2("Skipping namespace: {0}", group.Key);
                    }

                    continue;
                }

                members.Add(
                    SF.NamespaceDeclaration(SF.ParseName(group.Key))
                    .AddUsings(
                        TypeUtils.GetNamespaces(typeof(TaskUtility), typeof(GrainExtensions))
                        .Select(_ => SF.UsingDirective(SF.ParseName(_)))
                        .ToArray())
                    .AddMembers(namespaceMembers.ToArray()));
            }

            return(new GeneratedSyntax
            {
                SourceAssemblies = assemblies,
                Syntax = members.Count > 0 ? SF.CompilationUnit().AddMembers(members.ToArray()) : null
            });
        }
示例#26
0
 protected virtual void AddCreateObjectReferenceMethods(GrainInterfaceData grainInterfaceData, CodeTypeDeclaration factoryClass)
 {
     throw new NotImplementedException("GrainNamespace.AddCreateObjectReferenceMethods");
 }
示例#27
0
        protected override string GetBasicMethodImpl(MethodInfo methodInfo)
        {
            var invokeArguments = GetInvokeArguments(methodInfo);

            int    methodId = GrainInterfaceData.ComputeMethodId(methodInfo);
            string methodImpl;
            string optional = null;

            if (GrainInterfaceData.IsReadOnly(methodInfo))
            {
                optional = ", options:= Global.Orleans.CodeGeneration.InvokeMethodOptions.ReadOnly";
            }

            if (GrainInterfaceData.IsUnordered(methodInfo))
            {
                if (optional == null)
                {
                    optional = ", options:= ";
                }
                else
                {
                    optional += " | ";
                }

                optional += " Global.Orleans.CodeGeneration.InvokeMethodOptions.Unordered";
            }

            if (GrainInterfaceData.IsAlwaysInterleave(methodInfo))
            {
                if (optional == null)
                {
                    optional = ", options:= ";
                }
                else
                {
                    optional += " | ";
                }

                optional += " Global.Orleans.CodeGeneration.InvokeMethodOptions.AlwaysInterleave";
            }

            if (methodInfo.ReturnType == typeof(void))
            {
                methodImpl = string.Format(@"
                MyBase.InvokeOneWayMethod({0}, New System.Object() {{{1}}} {2})",
                                           methodId, invokeArguments, optional);
            }
            else
            {
                if (methodInfo.ReturnType == typeof(Task))
                {
                    methodImpl = string.Format(@"
                Return MyBase.InvokeMethodAsync(Of System.Object)({0}, New System.Object() {{{1}}} {2})",
                                               methodId,
                                               invokeArguments,
                                               optional);
                }
                else
                {
                    methodImpl = string.Format(@"
                Return MyBase.InvokeMethodAsync(Of {0})({1}, New System.Object() {{{2}}} {3})",
                                               GetActualMethodReturnType(methodInfo.ReturnType, SerializeFlag.NoSerialize),
                                               methodId,
                                               invokeArguments,
                                               optional);
                }
            }
            return(GetParamGuardCheckStatements(methodInfo) + methodImpl);
        }
示例#28
0
        protected override void AddGetGrainMethods(GrainInterfaceData iface, CodeTypeDeclaration factoryClass)
        {
            RecordReferencedNamespaceAndAssembly(typeof(GrainId));
            RecordReferencedNamespaceAndAssembly(iface.Type);
            var             interfaceId = GrainInterfaceData.GetGrainInterfaceId(iface.Type);
            Action <string> add         = codeFmt => factoryClass.Members.Add(
                new CodeSnippetTypeMember(String.Format(codeFmt, iface.InterfaceTypeName, interfaceId)));

            bool hasKeyExt    = GrainInterfaceData.UsesPrimaryKeyExtension(iface.Type);
            bool isGuidKey    = typeof(IGrainWithGuidKey).IsAssignableFrom(iface.Type);
            bool isLongKey    = typeof(IGrainWithIntegerKey).IsAssignableFrom(iface.Type);
            bool isStringKey  = typeof(IGrainWithStringKey).IsAssignableFrom(iface.Type);
            bool isDefaultKey = !(isGuidKey || isStringKey || isLongKey);

            if (isDefaultKey && hasKeyExt)
            {
                // the programmer has specified [ExtendedPrimaryKey] on the interface.
                add(@"
                        public static {0} GetGrain(long primaryKey, string keyExt)
                        {{
                            return Cast(global::Orleans.CodeGeneration.GrainFactoryBase.MakeKeyExtendedGrainReferenceInternal(typeof({0}), {1}, primaryKey, keyExt));
                        }}");

                add(@"
                        public static {0} GetGrain(long primaryKey, string keyExt, string grainClassNamePrefix)
                        {{
                            return Cast(global::Orleans.CodeGeneration.GrainFactoryBase.MakeKeyExtendedGrainReferenceInternal(typeof({0}), {1}, primaryKey, keyExt, grainClassNamePrefix));
                        }}");

                add(@"
                        public static {0} GetGrain(System.Guid primaryKey, string keyExt)
                        {{
                            return Cast(global::Orleans.CodeGeneration.GrainFactoryBase.MakeKeyExtendedGrainReferenceInternal(typeof({0}), {1}, primaryKey, keyExt));
                        }}");

                add(@"
                        public static {0} GetGrain(System.Guid primaryKey, string keyExt, string grainClassNamePrefix)
                        {{
                            return Cast(global::Orleans.CodeGeneration.GrainFactoryBase.MakeKeyExtendedGrainReferenceInternal(typeof({0}), {1}, primaryKey, keyExt,grainClassNamePrefix));
                        }}");
            }
            else
            {
                // the programmer has not specified [ExplicitPlacement] on the interface nor [ExtendedPrimaryKey].
                if (isLongKey || isDefaultKey)
                {
                    add(@"
                        public static {0} GetGrain(long primaryKey)
                        {{
                            return Cast(global::Orleans.CodeGeneration.GrainFactoryBase.MakeGrainReferenceInternal(typeof({0}), {1}, primaryKey));
                        }}");

                    add(@"
                        public static {0} GetGrain(long primaryKey, string grainClassNamePrefix)
                        {{
                            return Cast(global::Orleans.CodeGeneration.GrainFactoryBase.MakeGrainReferenceInternal(typeof({0}), {1}, primaryKey, grainClassNamePrefix));
                        }}");
                }

                if (isGuidKey || isDefaultKey)
                {
                    add(@"
                        public static {0} GetGrain(System.Guid primaryKey)
                        {{
                            return Cast(global::Orleans.CodeGeneration.GrainFactoryBase.MakeGrainReferenceInternal(typeof({0}), {1}, primaryKey));
                        }}");

                    add(@"
                        public static {0} GetGrain(System.Guid primaryKey, string grainClassNamePrefix)
                        {{
                            return Cast(global::Orleans.CodeGeneration.GrainFactoryBase.MakeGrainReferenceInternal(typeof({0}), {1}, primaryKey, grainClassNamePrefix));
                        }}");
                }

                if (isStringKey)
                {
                    add(@"
                        public static {0} GetGrain(System.String primaryKey)
                        {{
                            return Cast(global::Orleans.CodeGeneration.GrainFactoryBase.MakeGrainReferenceInternal(typeof({0}), {1}, primaryKey));
                        }}");

                    add(@"
                        public static {0} GetGrain(System.String primaryKey, string grainClassNamePrefix)
                        {{
                            return Cast(global::Orleans.CodeGeneration.GrainFactoryBase.MakeGrainReferenceInternal(typeof({0}), {1}, primaryKey, grainClassNamePrefix));
                        }}");
                }
            }
        }
示例#29
0
        /// <summary>
        /// Generates switch cases for the provided grain type.
        /// </summary>
        /// <param name="grainType">
        /// The grain type.
        /// </param>
        /// <param name="methodIdArgument">
        /// The method id argument, which is used to select the correct switch label.
        /// </param>
        /// <param name="generateMethodHandler">
        /// The function used to generate switch block statements for each method.
        /// </param>
        /// <returns>
        /// The switch cases for the provided grain type.
        /// </returns>
        public static SwitchSectionSyntax[] GenerateGrainInterfaceAndMethodSwitch(
            Type grainType,
            IdentifierNameSyntax methodIdArgument,
            Func <MethodInfo, StatementSyntax[]> generateMethodHandler)
        {
            var interfaces = GrainInterfaceData.GetRemoteInterfaces(grainType);

            interfaces[GrainInterfaceData.GetGrainInterfaceId(grainType)] = grainType;

            // Switch on interface id.
            var interfaceCases = new List <SwitchSectionSyntax>();

            foreach (var @interface in interfaces)
            {
                var interfaceType = @interface.Value;
                var interfaceId   = @interface.Key;
                var methods       = GrainInterfaceData.GetMethods(interfaceType);

                var methodCases = new List <SwitchSectionSyntax>();

                // Switch on method id.
                foreach (var method in methods)
                {
                    // Generate switch case.
                    var methodId   = GrainInterfaceData.ComputeMethodId(method);
                    var methodType = method;

                    // Generate the switch label for this interface id.
                    var methodIdSwitchLabel =
                        SF.CaseSwitchLabel(
                            SF.LiteralExpression(SyntaxKind.NumericLiteralExpression, SF.Literal(methodId)));

                    // Generate the switch body.
                    var methodInvokeStatement = generateMethodHandler(methodType);

                    methodCases.Add(
                        SF.SwitchSection().AddLabels(methodIdSwitchLabel).AddStatements(methodInvokeStatement));
                }

                // Generate the switch label for this interface id.
                var interfaceIdSwitchLabel =
                    SF.CaseSwitchLabel(
                        SF.LiteralExpression(SyntaxKind.NumericLiteralExpression, SF.Literal(interfaceId)));

                // Generate the default case, which will throw a NotImplementedException.
                var errorMessage = SF.BinaryExpression(
                    SyntaxKind.AddExpression,
                    "interfaceId=".GetLiteralExpression(),
                    SF.BinaryExpression(
                        SyntaxKind.AddExpression,
                        SF.LiteralExpression(SyntaxKind.NumericLiteralExpression, SF.Literal(interfaceId)),
                        SF.BinaryExpression(
                            SyntaxKind.AddExpression,
                            ",methodId=".GetLiteralExpression(),
                            methodIdArgument)));
                var throwStatement =
                    SF.ThrowStatement(
                        SF.ObjectCreationExpression(typeof(NotImplementedException).GetTypeSyntax())
                        .AddArgumentListArguments(SF.Argument(errorMessage)));
                var defaultCase = SF.SwitchSection().AddLabels(SF.DefaultSwitchLabel()).AddStatements(throwStatement);

                // Generate switch statements for the methods in this interface.
                var methodSwitchStatements =
                    SF.SwitchStatement(methodIdArgument).AddSections(methodCases.ToArray()).AddSections(defaultCase);

                // Generate the switch section for this interface.
                interfaceCases.Add(
                    SF.SwitchSection().AddLabels(interfaceIdSwitchLabel).AddStatements(methodSwitchStatements));
            }

            return(interfaceCases.ToArray());
        }
示例#30
0
 /// <summary>
 /// Returns the Visual Basic name for the provided <paramref name="parameter"/>.
 /// </summary>
 /// <param name="parameter">The parameter.</param>
 /// <returns>The Visual Basic name for the provided <paramref name="parameter"/>.</returns>
 protected override string GetParameterName(ParameterInfo parameter)
 {
     return(string.Format("[{0}]", GrainInterfaceData.GetParameterName(parameter)));
 }