예제 #1
0
        internal void AddEntry(int interfaceId, Type iface, int grainTypeCode, string grainInterface, string grainClass, string assembly, 
                                bool isGenericGrainClass, PlacementStrategy placement, bool primaryImplementation = false)
        {
            lock (this)
            {
                GrainInterfaceData grainInterfaceData;

                if (table.ContainsKey(interfaceId))
                {
                    grainInterfaceData = table[interfaceId];
                }
                else
                {
                    grainInterfaceData = new GrainInterfaceData(interfaceId, iface, grainInterface);

                    table[interfaceId] = grainInterfaceData;
                    var interfaceTypeKey = GetTypeKey(iface, isGenericGrainClass);
                    typeToInterfaceData[interfaceTypeKey] = grainInterfaceData;
                }

                var implementation = new GrainClassData(grainTypeCode, grainClass, isGenericGrainClass, grainInterfaceData, placement);
                if (!implementationIndex.ContainsKey(grainTypeCode))
                    implementationIndex.Add(grainTypeCode, implementation);

                grainInterfaceData.AddImplementation(implementation, primaryImplementation);
                if (primaryImplementation)
                {
                    primaryImplementations[grainInterface] = grainClass;
                }
                else
                {
                    if (!primaryImplementations.ContainsKey(grainInterface))
                        primaryImplementations.Add(grainInterface, grainClass);
                }

                if (localTestMode)
                {
                    if (!loadedGrainAsemblies.Contains(assembly))
                        loadedGrainAsemblies.Add(assembly);
                }
            }
        }
예제 #2
0
        protected override void AddCreateObjectReferenceMethods(GrainInterfaceData grainInterfaceData, CodeTypeDeclaration factoryClass)
        {
            var fieldImpl = @"Private Shared methodInvoker As Global.Orleans.CodeGeneration.IGrainMethodInvoker";
            var invokerField = new CodeSnippetTypeMember(fieldImpl);
            factoryClass.Members.Add(invokerField);

            var methodImpl = String.Format(@"
        Public Shared Async Function CreateObjectReference(obj As {0}) As System.Threading.Tasks.Task(Of {0})       
            If methodInvoker Is Nothing Then : methodInvoker = New {2}() : End If
            Return {1}.Cast(Await Global.Orleans.Runtime.GrainReference.CreateObjectReference(obj, methodInvoker))
        End Function",
            grainInterfaceData.TypeName,
            grainInterfaceData.FactoryClassName,
            grainInterfaceData.InvokerClassName);
            var createObjectReferenceMethod = new CodeSnippetTypeMember(methodImpl);
            factoryClass.Members.Add(createObjectReferenceMethod);

            methodImpl = String.Format(@"
        Public Shared Function DeleteObjectReference(reference As {0}) As System.Threading.Tasks.Task
            Return Global.Orleans.Runtime.GrainReference.DeleteObjectReference(reference)
        End Function",
            grainInterfaceData.TypeName);
            var deleteObjectReferenceMethod = new CodeSnippetTypeMember(methodImpl);
            factoryClass.Members.Add(deleteObjectReferenceMethod);
        }
예제 #3
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)));

            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(@"
                        [System.Obsolete(""This method has been deprecated. Please use GrainFactory.GetGrain<{0}> instead."")]
                        public static {0} GetGrain(long primaryKey, string keyExt)
                        {{
                            return Cast(global::Orleans.CodeGeneration.GrainFactoryBase.MakeKeyExtendedGrainReferenceInternal(typeof({0}), primaryKey, keyExt));
                        }}");

                add(@"
                        [System.Obsolete(""This method has been deprecated. Please use GrainFactory.GetGrain<{0}> instead."")]
                        public static {0} GetGrain(long primaryKey, string keyExt, string grainClassNamePrefix)
                        {{
                            return Cast(global::Orleans.CodeGeneration.GrainFactoryBase.MakeKeyExtendedGrainReferenceInternal(typeof({0}), primaryKey, keyExt, grainClassNamePrefix));
                        }}");
            }
            else if (isGuidCompoundKey)
            {
                add(@"
                        [System.Obsolete(""This method has been deprecated. Please use GrainFactory.GetGrain<{0}> instead."")]
                        public static {0} GetGrain(System.Guid primaryKey, string keyExt)
                        {{
                            return Cast(global::Orleans.CodeGeneration.GrainFactoryBase.MakeKeyExtendedGrainReferenceInternal(typeof({0}), primaryKey, keyExt));
                        }}");

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

                    add(@"
                        [System.Obsolete(""This method has been deprecated. Please use GrainFactory.GetGrain<{0}> instead."")]
                        public static {0} GetGrain(long primaryKey, string grainClassNamePrefix)
                        {{
                            return Cast(global::Orleans.CodeGeneration.GrainFactoryBase.MakeGrainReferenceInternal(typeof({0}), primaryKey, grainClassNamePrefix));
                        }}");
                }

                if (isGuidKey || isDefaultKey)
                {
                    add(@"
                        [System.Obsolete(""This method has been deprecated. Please use GrainFactory.GetGrain<{0}> instead."")]
                        public static {0} GetGrain(System.Guid primaryKey)
                        {{
                            return Cast(global::Orleans.CodeGeneration.GrainFactoryBase.MakeGrainReferenceInternal(typeof({0}), primaryKey));
                        }}");

                    add(@"
                        [System.Obsolete(""This method has been deprecated. Please use GrainFactory.GetGrain<{0}> instead."")]
                        public static {0} GetGrain(System.Guid primaryKey, string grainClassNamePrefix)
                        {{
                            return Cast(global::Orleans.CodeGeneration.GrainFactoryBase.MakeGrainReferenceInternal(typeof({0}), primaryKey, grainClassNamePrefix));
                        }}");
                }

                if (isStringKey)
                {
                    add(@"
                        [System.Obsolete(""This method has been deprecated. Please use GrainFactory.GetGrain<{0}> instead."")]
                        public static {0} GetGrain(System.String primaryKey)
                        {{
                            return Cast(global::Orleans.CodeGeneration.GrainFactoryBase.MakeGrainReferenceInternal(typeof({0}), primaryKey));
                        }}");

                    add(@"
                        [System.Obsolete(""This method has been deprecated. Please use GrainFactory.GetGrain<{0}> instead."")]
                        public static {0} GetGrain(System.String primaryKey, string grainClassNamePrefix)
                        {{
                            return Cast(global::Orleans.CodeGeneration.GrainFactoryBase.MakeGrainReferenceInternal(typeof({0}), primaryKey, grainClassNamePrefix));
                        }}");
                }
            }
        }
예제 #4
0
        protected override void AddCreateObjectReferenceMethods(GrainInterfaceData grainInterfaceData, CodeTypeDeclaration factoryClass)
        {
            var fieldImpl = @"
        private static global::Orleans.CodeGeneration.IGrainMethodInvoker methodInvoker;";
            var invokerField = new CodeSnippetTypeMember(fieldImpl);
            factoryClass.Members.Add(invokerField);

            var methodImpl = String.Format(@"
        public async static System.Threading.Tasks.Task<{0}> CreateObjectReference({0} obj)
        {{
            if (methodInvoker == null) methodInvoker = new {2}();
            return {1}.Cast(await global::Orleans.Runtime.GrainReference.CreateObjectReference(obj, methodInvoker));
        }}", grainInterfaceData.TypeName, grainInterfaceData.FactoryClassName, grainInterfaceData.InvokerClassName);
            var createObjectReferenceMethod = new CodeSnippetTypeMember(methodImpl);
            factoryClass.Members.Add(createObjectReferenceMethod);

            methodImpl = String.Format(@"
        public static System.Threading.Tasks.Task DeleteObjectReference({0} reference)
        {{
            return global::Orleans.Runtime.GrainReference.DeleteObjectReference(reference);
        }}",
            grainInterfaceData.TypeName);
            var deleteObjectReferenceMethod = new CodeSnippetTypeMember(methodImpl);
            factoryClass.Members.Add(deleteObjectReferenceMethod);
        }
예제 #5
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");
 }
예제 #6
0
 protected override string GetInvokerImpl(GrainInterfaceData si, CodeTypeDeclaration invokerClass, Type grainType, GrainInterfaceInfo grainInterfaceInfo, bool isClient)
 {
     throw new NotImplementedException("GetInvokerImpl");
 }
예제 #7
0
        protected override CodeTypeDeclaration GetStateClass(GrainInterfaceData grainInterfaceData, Action<Type> referred, string stateClassBaseName, string stateClassName, out bool hasStateClass)
        {
            var sourceType = grainInterfaceData.Type;
            stateClassName = FixupTypeName(stateClassName);
            CodeTypeParameterCollection genericTypeParams = grainInterfaceData.GenericTypeParams;
            Func<Type, bool> nonamespace = t => false;
            Type persistentInterface = GetPersistentInterface(sourceType);
            
            Dictionary<string, PropertyInfo> asyncProperties = GrainInterfaceData.GetPersistentProperties(persistentInterface)
                .ToDictionary(p => p.Name.Substring(p.Name.LastIndexOf('.') + 1), p => p);

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

            hasStateClass = properties.Count > 0;

            if (!hasStateClass) return null;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            // Generate the serialization members.

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

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

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

            DecreaseIndent();

            return null;
        }
예제 #8
0
 internal GrainClassData(int grainTypeCode, string grainClass, bool isGeneric, GrainInterfaceData interfaceData, PlacementStrategy placement)
 {
     GrainTypeCode = grainTypeCode;
     GrainClass = grainClass;
     this.isGeneric = isGeneric;
     this.interfaceData = interfaceData;
     genericClassNames = new Dictionary<string, string>(); // TODO: initialize only for generic classes
     placementStrategy = placement ?? PlacementStrategy.GetDefault();
 }
예제 #9
0
 protected virtual void AddCreateObjectReferenceMethods(GrainInterfaceData grainInterfaceData, CodeTypeDeclaration factoryClass)
 {
     throw new NotImplementedException("GrainNamespace.AddCreateObjectReferenceMethods");
 }
예제 #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);

            if (persistentInterface!=null)
            {
                if (!sourceType.GetCustomAttributes(typeof (StorageProviderAttribute)).Any())
                    ReportError(String.Format("No StorageProvider attribute specified for grain class {0}", sourceType.FullName));
                    
                if (!persistentInterface.IsInterface)
                {
                    hasStateClass = false;
                    return null;
                }
                else
                {
                    ConsoleText.WriteError(String.Format("Warning: Usage of grain state interfaces as type arguments for Grain<T> has been deprecated. " +
                        "Define an equivalent class with automatic properties instead of the state interface for {0}.", sourceType.FullName));
                }
            }

            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, language: language)))));

            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, language)));
            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;
        }
예제 #11
0
        private static bool TryGetGrainClassData(GrainInterfaceData interfaceData, out GrainClassData implementation, string grainClassNamePrefix)
        {
            implementation = null;
            var implementations = interfaceData.Implementations;

            if (implementations.Length == 0)
            {
                return(false);
            }

            if (String.IsNullOrEmpty(grainClassNamePrefix))
            {
                if (implementations.Length == 1)
                {
                    implementation = implementations[0];
                    return(true);
                }

                if (interfaceData.PrimaryImplementation != null)
                {
                    implementation = interfaceData.PrimaryImplementation;
                    return(true);
                }

                throw new OrleansException(String.Format("Cannot resolve grain interface ID={0} to a grain class because of multiple implementations of it: {1}",
                                                         interfaceData.InterfaceId, Utils.EnumerableToString(implementations, d => d.GrainClass, ",", false)));
            }

            if (implementations.Length == 1)
            {
                if (implementations[0].GrainClass.StartsWith(grainClassNamePrefix, StringComparison.Ordinal))
                {
                    implementation = implementations[0];
                    return(true);
                }

                return(false);
            }

            var matches = implementations.Where(impl => impl.GrainClass.Equals(grainClassNamePrefix)).ToArray(); //exact match?

            if (matches.Length == 0)
            {
                matches = implementations.Where(
                    impl => impl.GrainClass.StartsWith(grainClassNamePrefix, StringComparison.Ordinal)).ToArray(); //prefix matches
            }
            if (matches.Length == 0)
            {
                return(false);
            }

            if (matches.Length == 1)
            {
                implementation = matches[0];
                return(true);
            }

            throw new OrleansException(String.Format("Cannot resolve grain interface ID={0}, grainClassNamePrefix={1} to a grain class because of multiple implementations of it: {2}",
                                                     interfaceData.InterfaceId,
                                                     grainClassNamePrefix,
                                                     Utils.EnumerableToString(matches, d => d.GrainClass, ",", false)));
        }
예제 #12
0
 private void AddFactoryMethods(GrainInterfaceData si, CodeTypeDeclaration factoryClass)
 {
     RecordReferencedNamespaceAndAssembly(si.Type);
 }
예제 #13
0
 internal GrainClassData(int grainTypeCode, string grainClass, bool isGeneric, GrainInterfaceData interfaceData, PlacementStrategy placement)
 {
     GrainTypeCode      = grainTypeCode;
     GrainClass         = grainClass;
     this.isGeneric     = isGeneric;
     this.interfaceData = interfaceData;
     genericClassNames  = new Dictionary <string, string>(); // TODO: initialize only for generic classes
     placementStrategy  = placement ?? PlacementStrategy.GetDefault();
 }
예제 #14
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)
        {
            string castImplCode;
            string checkCode = null;

            if (isFactory)
            {
                castImplCode = string.Format(@"{0}.Cast(grainRef)", FixupTypeName(si.ReferenceClassName));

                if (si.IsSystemTarget)
                    checkCode = 
                        @"If  Not ((Global.Orleans.Runtime.GrainReference)grainRef).IsInitializedSystemTarget Then
                            Throw New InvalidOperationException(""InvalidCastException cast of a system target grain reference. Must have SystemTargetSilo set to the target silo address"")
                          End If";
            }
            else
            {
                castImplCode = string.Format(
                    @"CType(Global.Orleans.Runtime.GrainReference.CastInternal(GetType({0}), Function(gr As GrainReference) New {1}(gr), grainRef, {2}),{0})",
                    FixupTypeName(si.InterfaceTypeName), // Interface type for references for this grain
                    FixupTypeName(si.ReferenceClassName), // Concrete class for references for this grain
                    GrainInterfaceData.GetGrainInterfaceId(si.Type));
            }

            var methodImpl = string.Format(@"
            {3} Shared Function Cast(grainRef As Global.Orleans.Runtime.IAddressable) As {0}           
                {1}
                Return {2}
            End Function",
                si.InterfaceTypeName.Replace("<", "(Of ").Replace(">", ")"),
                checkCode,
                castImplCode,
                "Public");

            var castMethod = new CodeSnippetTypeMember(methodImpl);
            referenceClass.Members.Add(castMethod);
        }
예제 #15
0
        protected override string GetInvokerImpl(GrainInterfaceData si, CodeTypeDeclaration invokerClass, Type grainType, GrainInterfaceInfo grainInterfaceInfo, bool isClient)
        {
            //No public method is implemented in this grain type for orleans messages
            if (grainInterfaceInfo.Interfaces.Count == 0)
            {
                return string.Format(@"
            Dim t = New System.Threading.Tasks.TaskCompletionSource(Of Object)()
            t.SetException(New NotImplementedException(""No grain interfaces for type {0}""))
            Return t.Task
                ", TypeUtils.GetFullName(grainType, Language.VisualBasic));
            }

            var builder = new StringBuilder();
            builder.Append(@"            Try
            ");

            var interfaceSwitchBody = String.Empty;
            foreach (int interfaceId in grainInterfaceInfo.Interfaces.Keys)
            {
                InterfaceInfo interfaceInfo = grainInterfaceInfo.Interfaces[interfaceId];
                interfaceSwitchBody += GetMethodDispatchSwitchForInterface(interfaceId, interfaceInfo);
            }

            builder.AppendFormat(
                @"If grain Is Nothing Then : Throw New System.ArgumentNullException(""grain"") : End If
                Select Case interfaceId
                    {0}
                    Case Else
                        {1}
                End Select", interfaceSwitchBody, "Throw New System.InvalidCastException(\"interfaceId=\"+interfaceId)");

            builder.Append(@"
            Catch ex As Exception
                Dim t = New System.Threading.Tasks.TaskCompletionSource(Of Object)()
                t.SetException(ex)
                Return t.Task
            End Try");

            return builder.ToString();
        }
예제 #16
0
 private void AddFactoryMethods(GrainInterfaceData si, CodeTypeDeclaration factoryClass)
 {
     RecordReferencedNamespaceAndAssembly(si.Type);
     if (GrainInterfaceData.IsGrainType(si.Type) && ShouldGenerateGetGrainMethods(si.Type))
         AddGetGrainMethods(si, factoryClass);
 }
예제 #17
0
        private static bool TryGetGrainClassData(GrainInterfaceData interfaceData, out GrainClassData implementation, string grainClassNamePrefix)
        {
            implementation = null;
            var implementations = interfaceData.Implementations;

            if (implementations.Length == 0)
                return false;

            if (String.IsNullOrEmpty(grainClassNamePrefix))
            {
                if (implementations.Length == 1)
                {
                    implementation = implementations[0];
                    return true;
                }

                if (interfaceData.PrimaryImplementation != null)
                {
                    implementation = interfaceData.PrimaryImplementation;
                    return true;
                }

                throw new OrleansException(String.Format("Cannot resolve grain interface ID={0} to a grain class because of multiple implementations of it: {1}",
                    interfaceData.InterfaceId, Utils.EnumerableToString(implementations, d => d.GrainClass, ",", false)));
            }

            if (implementations.Length == 1)
            {
                if (implementations[0].GrainClass.StartsWith(grainClassNamePrefix, StringComparison.Ordinal))
                {
                    implementation = implementations[0];
                    return true;
                }

                return false;
            }

            var matches = implementations.Where(impl => impl.GrainClass.Equals(grainClassNamePrefix)).ToArray(); //exact match?
            if (matches.Length == 0)
                matches = implementations.Where(
                    impl => impl.GrainClass.StartsWith(grainClassNamePrefix, StringComparison.Ordinal)).ToArray(); //prefix matches

            if (matches.Length == 0)
                return false;

            if (matches.Length == 1)
            {
                implementation = matches[0];
                return true;
            }

            throw new OrleansException(String.Format("Cannot resolve grain interface ID={0}, grainClassNamePrefix={1} to a grain class because of multiple implementations of it: {2}",
                interfaceData.InterfaceId,
                grainClassNamePrefix,
                Utils.EnumerableToString(matches, d => d.GrainClass, ",", false)));
        }
예제 #18
0
 protected virtual void AddGetGrainMethods(GrainInterfaceData iface, CodeTypeDeclaration factoryClass)
 {
     throw new NotImplementedException("GrainNamespace.AddGetGrainMethods");
 }
예제 #19
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");
 }
예제 #20
0
        private void GetActivationNamespace(CodeNamespace factoryNamespace, GrainInterfaceData grainInterfaceData)
        {
            if (!typeof (Grain).IsAssignableFrom(grainInterfaceData.Type)) return;

            // generate a state class
            bool hasStateClass;
            var code = GetStateClass(grainInterfaceData,
                RecordReferencedNamespaceAndAssembly,
                grainInterfaceData.StateClassBaseName,
                grainInterfaceData.StateClassName,
                out hasStateClass);

            if (code != null && hasStateClass)
                factoryNamespace.Types.Add(code);
        }
예제 #21
0
 protected override void AddCreateObjectReferenceMethods(GrainInterfaceData grainInterfaceData, CodeTypeDeclaration factoryClass)
 {
     throw new NotImplementedException("AddCreateObjectReferenceMethods");
 }
예제 #22
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, language: language))),
                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;
        }
예제 #23
0
 protected override void AddGetGrainMethods(GrainInterfaceData iface, CodeTypeDeclaration factoryClass)
 {
     throw new NotImplementedException("AddGetGrainMethods");
 }
예제 #24
0
 internal void AddStateClass(GrainInterfaceData interfaceData)
 {
     GetActivationNamespace(ReferencedNamespace, interfaceData);
 }
예제 #25
0
        /// <summary>
        /// Read a grain assembly and extract codegen info for each Orleans grain / service interface
        /// </summary>
        /// <param name="inputAssembly">Input grain assembly</param>
        /// <param name="namespaceDictionary">output list of grain namespace</param>
        /// <param name="outputAssemblyName">Output assembly being generated</param>
        /// <param name="options">Code generation options</param>
        internal bool ProcessInputAssembly(
            Assembly inputAssembly, 
            Dictionary<string, NamespaceGenerator> namespaceDictionary, 
            string outputAssemblyName, 
            CodeGenOptions options)
        {
            if(!Debugger.IsAttached)
                ReferenceResolver.AssertUniqueLoadForEachAssembly();

            var processedGrainTypes = new List<string>();
            bool success = true;

            ConsoleText.WriteStatus("Orleans-CodeGen - Adding grain namespaces from input Assembly " + inputAssembly.GetName());
            foreach (var type in inputAssembly.GetTypes())
            {
                if (!type.IsNested && !type.IsGenericParameter && type.IsSerializable)
                    SerializerGenerationManager.RecordTypeToGenerate(type);

                if (!options.ServerGen && GrainInterfaceData.IsGrainInterface(type))
                {
                    NamespaceGenerator grainNamespace = RegisterNamespace(inputAssembly, namespaceDictionary, type, options.TargetLanguage.Value);
                    processedGrainTypes.Add(type.FullName);

                    try
                    {
                        var grainInterfaceData = new GrainInterfaceData(options.TargetLanguage.Value, type);
                        grainNamespace.AddReferenceClass(grainInterfaceData);
                    }
                    catch (GrainInterfaceData.RulesViolationException rve)
                    {
                        foreach (var v in rve.Violations)
                            NamespaceGenerator.ReportError(v);

                        success = false;
                    }
                }

                if (options.ServerGen && !type.IsAbstract && (GrainInterfaceData.IsAddressable(type)))
                {
                    var grainNamespace = RegisterNamespace(inputAssembly, namespaceDictionary, type, options.TargetLanguage.Value);
                    try
                    {
                        var grainInterfaceData = GrainInterfaceData.FromGrainClass(type, options.TargetLanguage.Value);
                    }
                    catch (GrainInterfaceData.RulesViolationException rve)
                    {
                        //Note: I have a separate try/catch here since we are issuing warnings instead of compile error unlike the Grain Interface validations above.
                        //Question: Should we instead throw compile errors?
                        //Question: What warning number should we use? Standard C# warning/error numbers are listed here: https://msdn.microsoft.com/en-us/library/ms228296(v=vs.90).aspx                        
                        foreach (var v in rve.Violations)
                            NamespaceGenerator.ReportWarning(string.Format("CS0184 : {0}", v));
                    }
                }
            }

            if (!success) return false;

            ConsoleText.WriteStatus("Orleans-CodeGen - Processed grain classes: ");
            foreach (string name in processedGrainTypes)
                ConsoleText.WriteStatus("\t" + name);

            // Generate serializers for types we encountered along the way
            SerializerGenerationManager.GenerateSerializers(inputAssembly, namespaceDictionary, outputAssemblyName, options.TargetLanguage.Value);
            return true;
        }
예제 #26
0
        private static bool ShouldGenerateObjectRefFactory(GrainInterfaceData ifaceData)
        {
            var ifaceType = ifaceData.Type;
            // generate CreateObjectReference in 2 cases:
            // 1) for interfaces derived from IGrainObserver
            // 2) when specifically specifies via FactoryTypes.ClientObject or FactoryTypes.Both 
           if(IsObserver(ifaceType))
                return true;

            var factoryType = FactoryAttribute.CollectFactoryTypesSpecified(ifaceType);
            return factoryType == FactoryAttribute.FactoryTypes.ClientObject || factoryType == FactoryAttribute.FactoryTypes.Both;
        }
예제 #27
0
        protected override string GetInvokerImpl(
            GrainInterfaceData si, 
            CodeTypeDeclaration invokerClass, 
            Type grainType, 
            GrainInterfaceInfo grainInterfaceInfo, 
            bool isClient)
        {
            //No public method is implemented in this grain type for orleans messages
            if (grainInterfaceInfo.Interfaces.Count == 0)
            {
                return string.Format(@"
                var t = new System.Threading.Tasks.TaskCompletionSource<object>();
                t.SetException(new NotImplementedException(""No grain interfaces for type {0}""));
                return t.Task;
                ", TypeUtils.GetFullName(grainType, Language.CSharp));
            }

            var builder = new StringBuilder();
            builder.AppendFormat(@"
            try
            {{");

            var interfaceSwitchBody = String.Empty;
            foreach (int interfaceId in grainInterfaceInfo.Interfaces.Keys)
            {
                InterfaceInfo interfaceInfo = grainInterfaceInfo.Interfaces[interfaceId];
                interfaceSwitchBody += GetMethodDispatchSwitchForInterface(interfaceId, interfaceInfo);
            }

            builder.AppendFormat(
                @"                    if (grain == null) throw new System.ArgumentNullException(""grain"");
                switch (interfaceId)
                {{
                    {0}
                    default:
                        {1};
                }}", interfaceSwitchBody, "throw new System.InvalidCastException(\"interfaceId=\"+interfaceId)");

            builder.AppendFormat(@"
            }}
            catch(Exception ex)
            {{
                var t = new System.Threading.Tasks.TaskCompletionSource<object>();
                t.SetException(ex);
                return t.Task;
            }}");

            return builder.ToString();
        }
예제 #28
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, language: language)))));

            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.Public | 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);
        }
예제 #29
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)
        {
            string castImplCode;
            string checkCode = null;
            if (isFactory)
            {
                castImplCode = string.Format(@"{0}.Cast(grainRef)", si.ReferenceClassName);

                if (si.IsSystemTarget)
                    checkCode = @"if(!((global::Orleans.Runtime.GrainReference)grainRef).IsInitializedSystemTarget)
                        throw new InvalidOperationException(""InvalidCastException cast of a system target grain reference. Must have SystemTargetSilo set to the target silo address"");";
            }
            else
            {
                castImplCode = string.Format(
                    @"({0}) global::Orleans.Runtime.GrainReference.CastInternal(typeof({0}), (global::Orleans.Runtime.GrainReference gr) => {{ return new {1}(gr);}}, grainRef, {2})",
                    si.InterfaceTypeName, // Interface type for references for this grain
                    si.ReferenceClassName, // Concrete class for references for this grain
                    GrainInterfaceData.GetGrainInterfaceId(si.Type));
            }

            var methodImpl = string.Format(@"
            {3} static {0} Cast(global::Orleans.Runtime.IAddressable grainRef)
            {{
                {1}
                return {2};
            }}", si.InterfaceTypeName, checkCode, castImplCode, "public");

            var castMethod = new CodeSnippetTypeMember(methodImpl);
            referenceClass.Members.Add(castMethod);
        }
예제 #30
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))));

            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}), 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}), 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}), 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}), 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}), 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}), 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}), 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}), 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}), 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}), primaryKey, grainClassNamePrefix))
                        End Function");
                }
            }
        }