Exemplo n.º 1
0
        private static CodeTypeReference BuildClassCodeTypeReference(this Type type, CodeNamespace ns,
                                                                     CodeTypeDeclaration[] declaredTypes)
        {
            if (!type.IsClass && !type.IsInterface)
            {
                throw new InvalidOperationException($"{type.Name} is not class or interface");
            }

            var res = new CodeTypeDeclaration(type.Name)
            {
                IsClass = type.IsClass, IsInterface = type.IsInterface
            };

            if (TypeAlreadyWasDeclared(res, ns, declaredTypes))
            {
                return(new CodeTypeReference(res.Name));
            }

            foreach (var prop in type.GetProperties(BindingFlags.Public | BindingFlags.Instance).ToArray())
            {
                res.GenerateProperty(prop.Name, BuildCodeTypeReference(prop.PropertyType, ns, declaredTypes),
                                     MemberAttributes.Public);
            }

            ns.Types.Add(res);
            return(new CodeTypeReference(res.Name));
        }
Exemplo n.º 2
0
        private static CodeCompileUnit BuildApi(Type type, string ns, string className,
                                                CodeTypeDeclaration[] declaredTypes)
        {
            CodeCompileUnit compileUnit = new CodeCompileUnit();

            var resNamespace = new CodeNamespace(ns);

            compileUnit.Namespaces.Add(resNamespace);

            var resClass = new CodeTypeDeclaration(className);

            resNamespace.Types.Add(resClass);
            resClass.IsPartial = true;

            var hubConnectionProperty = resClass.GenerateProperty("HubConnection",
                                                                  new CodeTypeReference(typeof(HubConnection).UseReflectionType(resNamespace)),
                                                                  MemberAttributes.Family | MemberAttributes.Final);

            var receivedApi = type.GetMethods()
                              .Where(x => x.GetCustomAttribute <ServerReceivedAttribute>() != null).Select(x =>
            {
                if (x.ReturnType != typeof(Task))
                {
                    throw new InvalidOperationException("Chathub methods return only async Task");
                }
                var res  = GenerateMethodsSignature(x, true, resNamespace, declaredTypes);
                var pars = x.GetParameters();

                var invokeParams = new List <CodeExpression> {
                    new CodePrimitiveExpression(x.Name)
                };
                invokeParams.AddRange(pars.Select(p => new CodeVariableReferenceExpression(p.Name)));

                var invokeExpr = new CodeMethodInvokeExpression(
                    new CodeVariableReferenceExpression(hubConnectionProperty.Name),
                    "InvokeAsync",
                    invokeParams.ToArray()
                    );
                invokeExpr.MarkCodeMethodInvokeExpressionAsAwait();
                res.Statements.Add(invokeExpr);
                return(res);
            }).ToArray();

            resClass.Members.AddRange(receivedApi);

            var sendApiMethods = type.Assembly.GetTypes()
                                 .Single(x => x.GetCustomAttribute <ClientApiAttribute>() != null)
                                 .GetMethods(BindingFlags.Public | BindingFlags.Static).Select(x =>
            {
                var pars = x.GetParameters().Where(p => p.ParameterType != typeof(IClientProxy))
                           .ToArray();
                var res = new CodeMemberMethod
                {
                    Name       = x.Name.FirstLetterToUppercase() + "On",
                    Attributes = MemberAttributes.Family | MemberAttributes.Final,
                    ReturnType =
                        new CodeTypeReference(CodeDomHelper.UseReflectionType(typeof(IDisposable), resNamespace)),
                };

                var parsExprs = pars.GetCodeParameters(resNamespace, declaredTypes);

                var typeParams  = parsExprs.Select(p => p.Type).ToArray();
                var handlerType = new CodeTypeReference("Action");
                handlerType.TypeArguments.AddRange(typeParams);

                var paramHandler = new CodeParameterDeclarationExpression(handlerType, "handler");
                res.Parameters.Add(paramHandler);

                var genericExpr = new CodeMethodInvokeExpression(
                    new CodeMethodReferenceExpression(
                        new CodeVariableReferenceExpression(hubConnectionProperty.Name),
                        "On",
                        typeParams),
                    new CodePrimitiveExpression(x.Name),
                    new CodeVariableReferenceExpression(paramHandler.Name));
                var returnStatement = new CodeMethodReturnStatement(genericExpr);
                res.Statements.Add(returnStatement);
                return(res);
            }).ToArray();

            resClass.Members.AddRange(sendApiMethods);

            return(compileUnit);
        }