Пример #1
0
        public void Initialize(Func <Type, object> factory)
        {
            var defaultSerializer  = GetResponseSerializer(DefaultSerializerType);
            var defaultDeserialzer = GetRequestDeserializer(DefaultDeserializerType);

            object serviceInstance = this;

            if (GetType() == typeof(Service))
            {
                if (factory == null)
                {
                    var constructor = DeclaringType.GetConstructor(Type.EmptyTypes);

                    if (constructor == null)
                    {
                        throw new ServiceBuilderException(
                                  "The '" + DeclaringType.DisplayName() + "' service is invalid. You " +
                                  "must either supply a factory method, provide a default public constructor, or inherit from " +
                                  GetType().DisplayName());
                    }

                    serviceInstance = constructor.Invoke(null);
                }
                else
                {
                    serviceInstance = factory(DeclaringType);
                }
            }

            var clientScript = new StringBuilder();

            clientScript.AppendLine("return {");
            var firstEndpoint = true;

            var methods = serviceInstance.GetType().GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

            foreach (var method in methods)
            {
                EndpointAttribute endpointAttribute = null;
                var parameterAttributes             = new List <EndpointParameterAttribute>();

                foreach (var attribute in method.GetCustomAttributes(false))
                {
                    if (attribute is EndpointAttribute)
                    {
                        endpointAttribute = (EndpointAttribute)attribute;
                    }
                    else if (attribute is EndpointParameterAttribute)
                    {
                        parameterAttributes.Add((EndpointParameterAttribute)attribute);
                    }
                }

                if (endpointAttribute != null)
                {
                    if (method.ReturnType != typeof(void))
                    {
                        throw new ServiceBuilderException(
                                  "The '" + method.Name + "' endpoint of the '" + Name +
                                  "' service has a return type, but it should have a return type of 'void'");
                    }

                    var methodParameters = method.GetParameters();

                    if (methodParameters.Length == 0 || methodParameters[0].ParameterType != typeof(IEndpointRequest))
                    {
                        throw new ServiceBuilderException(
                                  "The '" + method.Name + "' endpoint of the '" + Name +
                                  "' service has the wrong parameter list, the first parameter must be " +
                                  "of type '" + typeof(IEndpointRequest).DisplayName() + "'");
                    }

                    var parameterNames = new string[methodParameters.Length];

                    if (methodParameters.Length > 1)
                    {
                        for (var i = 1; i < methodParameters.Length; i++)
                        {
                            var methodParameter = methodParameters[i];
                            EndpointParameterAttribute endpointParameterAttribute = null;

                            foreach (var attribute in methodParameter.GetCustomAttributes(false))
                            {
                                endpointParameterAttribute = attribute as EndpointParameterAttribute;
                                if (endpointParameterAttribute != null)
                                {
                                    if (string.IsNullOrEmpty(endpointParameterAttribute.ParameterName))
                                    {
                                        endpointParameterAttribute.ParameterName = methodParameter.Name;
                                    }

                                    if (endpointParameterAttribute.ParserType == null)
                                    {
                                        endpointParameterAttribute.ParserType = methodParameter.ParameterType;
                                    }

                                    break;
                                }
                            }

                            if (endpointParameterAttribute == null)
                            {
                                endpointParameterAttribute = new EndpointParameterAttribute
                                {
                                    ParameterName = methodParameter.Name,
                                    ParameterType = EndpointParameterType.QueryString,
                                    ParserType    = methodParameter.ParameterType
                                };
                            }

                            parameterAttributes.Add(endpointParameterAttribute);
                            parameterNames[i] = endpointParameterAttribute.ParameterName;
                        }
                    }

                    var path = method.Name.ToLower();
                    if (!string.IsNullOrEmpty(endpointAttribute.UrlPath))
                    {
                        path = endpointAttribute.UrlPath;
                    }

                    var relativePath = !path.StartsWith("/");
                    if (relativePath)
                    {
                        path = BasePath + path;
                    }

                    var m = method;

                    Action <IEndpointRequest> action;
                    if (methodParameters.Length == 1)
                    {
                        action = r => m.Invoke(serviceInstance, new[] { r });
                    }
                    else
                    {
                        action = r =>
                        {
                            var parameters = new object[parameterNames.Length];

                            parameters[0] = r;

                            for (var i = 1; i < parameterNames.Length; i++)
                            {
                                parameters[i] = r.GetParameter(parameterNames[i]);
                            }

                            m.Invoke(serviceInstance, parameters);
                        }
                    };

                    var httpMethods = endpointAttribute.Methods ?? Methods;

                    var endpoint = new ServiceEndpoint(
                        path,
                        httpMethods,
                        action,
                        m,
                        endpointAttribute.ScenarioName,
                        endpointAttribute.Analytics,
                        _serviceDependenciesFactory.DataCatalog,
                        _serviceDependenciesFactory.DataDependencyFactory,
                        _serviceDependenciesFactory.RequestRouter)
                    {
                        RequestDeserializer = endpointAttribute.RequestDeserializer == null
                            ? defaultDeserialzer
                            : GetRequestDeserializer(endpointAttribute.RequestDeserializer),
                        ResponseSerializer = endpointAttribute.ResponseSerializer == null
                            ? defaultSerializer
                            : GetResponseSerializer(endpointAttribute.ResponseSerializer),
                    };

                    AddAnalysable(endpoint);

                    var runable = (IRunable)endpoint;
                    runable.Name           = method.Name;
                    runable.AllowAnonymous = AllowAnonymous;
                    runable.CacheCategory  = CacheCategory;
                    runable.CachePriority  = CachePriority;
                    runable.Package        = Package;

                    if (endpointAttribute.RequiredPermission == null)
                    {
                        if (!string.IsNullOrEmpty(RequiredPermission))
                        {
                            runable.RequiredPermission = RequiredPermission;
                            if (EndpointSpecificPermission)
                            {
                                runable.SecureResource = Name + "/" + runable.Name;
                            }
                        }
                    }
                    else
                    {
                        runable.RequiredPermission = endpointAttribute.RequiredPermission;
                    }

                    foreach (var parameter in parameterAttributes)
                    {
                        var parameterParser = GetParameterParser(parameter.ParserType);
                        endpoint.AddParameter(parameter.ParameterName, parameter.ParameterType, parameterParser);
                    }

                    Register(endpoint, httpMethods, relativePath, endpointAttribute.ScenarioName);

                    if (!firstEndpoint)
                    {
                        clientScript.AppendLine("  },");
                    }
                    firstEndpoint = false;

                    var queryStringParameters = parameterAttributes
                                                .Where(p => (p.ParameterType & EndpointParameterType.QueryString) == EndpointParameterType.QueryString)
                                                .Select(p => p.ParameterName)
                                                .ToList();

                    var pathParameters = parameterAttributes
                                         .Where(p => (p.ParameterType & (EndpointParameterType.PathSegment | EndpointParameterType.QueryString)) == EndpointParameterType.PathSegment)
                                         .Select(p => p.ParameterName)
                                         .ToList();

                    var headerParameters = parameterAttributes
                                           .Where(p => (p.ParameterType & (EndpointParameterType.Header | EndpointParameterType.PathSegment | EndpointParameterType.QueryString)) == EndpointParameterType.Header)
                                           .Select(p => p.ParameterName)
                                           .ToList();

                    var formParameters = parameterAttributes
                                         .Where(p => (p.ParameterType & (EndpointParameterType.FormField | EndpointParameterType.Header | EndpointParameterType.PathSegment | EndpointParameterType.QueryString)) == EndpointParameterType.FormField)
                                         .Select(p => p.ParameterName)
                                         .ToList();

                    var methodName = char.ToLower(method.Name[0]) + method.Name.Substring(1);
                    clientScript.AppendLine("  " + methodName + ": function(params, onSuccess, onDone, onFail) {");
                    clientScript.AppendLine("    var request = { isSuccess: function(ajax){ return ajax.status === 200; } };");
                    clientScript.AppendLine("    if (params != undefined && params.body != undefined) request.body = params.body;");

                    if (pathParameters.Count > 0)
                    {
                        var url = "\"" + path.ToLower() + "\"";
                        foreach (var parameter in pathParameters)
                        {
                            url = url.Replace("{" + parameter.ToLower() + "}", "\" + encodeURIComponent(params." + parameter + ") + \"");
                        }
                        if (url.EndsWith(" + \"\""))
                        {
                            url = url.Substring(0, url.Length - 5);
                        }
                        if (url.StartsWith("\"\" + "))
                        {
                            url = url.Substring(5);
                        }
                        clientScript.AppendLine("    request.url = " + url + ";");
                    }
                    else
                    {
                        clientScript.AppendLine("    request.url = \"" + path + "\";");
                    }

                    if (queryStringParameters.Count > 0)
                    {
                        clientScript.AppendLine("    var query = \"\";");
                        clientScript.AppendLine("    if (params != undefined) {");
                        foreach (var parameter in queryStringParameters)
                        {
                            clientScript.AppendLine("      if (params." + parameter + " != undefined) query += \"&" + parameter + "=\" + encodeURIComponent(params." + parameter + ");");
                        }
                        clientScript.AppendLine("    }");
                        clientScript.AppendLine("    if (query.length > 0) request.url += \"?\" + query.substring(1);");
                    }

                    if (headerParameters.Count > 0)
                    {
                        clientScript.AppendLine("    request.headers = [");
                        for (var i = 0; i < headerParameters.Count; i++)
                        {
                            var headerParameter = headerParameters[i];
                            clientScript.AppendLine("      { name: \"" + headerParameter + "\", value: params." + headerParameter + " }" + (i == headerParameters.Count - 1 ? "" : ","));
                        }
                        clientScript.AppendLine("    ];");
                    }

                    if (formParameters.Count > 0)
                    {
                        clientScript.AppendLine("    if (params != undefined) {");
                        clientScript.AppendLine("      var form = \"\";");
                        foreach (var parameter in formParameters)
                        {
                            clientScript.AppendLine("      if (params." + parameter + " != undefined) form += \"&" + parameter + "=\" + encodeURIComponent(params." + parameter + ");");
                        }
                        clientScript.AppendLine("      if (form.length > 0) {");
                        clientScript.AppendLine("        request.body = form.substring(1);");
                        clientScript.AppendLine("      }");
                        clientScript.AppendLine("    }");
                    }

                    clientScript.AppendLine("    if (onSuccess != undefined) request.onSuccess = function(ajax){ onSuccess(ajax.response); }");
                    clientScript.AppendLine("    if (onFail != undefined) request.onFail = onFail;");
                    clientScript.AppendLine("    if (onDone != undefined) request.onDone = onDone;");

                    for (var i = httpMethods.Length - 1; i >= 0; i--)
                    {
                        var httpMethod   = httpMethods[i];
                        var functionCall = string.Empty;

                        switch (httpMethod)
                        {
                        case Method.Get:
                            functionCall = "ns.ajax.restModule.getJson(request)";
                            break;

                        case Method.Post:
                            functionCall = formParameters.Count > 0 ? "ns.ajax.restModule.postForm(request)" : "ns.ajax.restModule.postJson(request)";
                            break;

                        case Method.Put:
                            functionCall = formParameters.Count > 0 ? "ns.ajax.restModule.putForm(request)" : "ns.ajax.restModule.putJson(request)";
                            break;

                        case Method.Delete:
                            functionCall = "ns.ajax.restModule.sendDelete(request)";
                            break;
                        }

                        if (httpMethods.Length == 1)
                        {
                            clientScript.AppendLine("    " + functionCall + ";");
                        }
                        else if (i == 0)
                        {
                            clientScript.AppendLine("    else " + functionCall + ";");
                        }
                        else if (i == httpMethods.Length - 1)
                        {
                            clientScript.AppendLine("    if (params.method == \"" + httpMethod.ToString().ToUpper() + "\") " + functionCall + ";");
                        }
                        else
                        {
                            clientScript.AppendLine("    else if (params.method == \"" + httpMethod.ToString().ToUpper() + "\") " + functionCall + ";");
                        }
                    }
                }
            }

            if (!firstEndpoint)
            {
                clientScript.AppendLine("  }");
            }
            clientScript.AppendLine("}");
            ClientScript = clientScript.ToString();
        }

        T IDebuggable.GetDebugInfo <T>(int parentDepth, int childDepth)
        {
            return(new DebugService() as T);
        }