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)); }
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); }