Я знаю, что эта ветка довольно старая, но у меня была эта проблема, и я придумал классное решение, которое может быть очень полезным для многих, потому что оно исправляет / расширяет библиотеку Volley по многим аспектам.
Я заметил некоторые неработающие функции Volley:
JSONObjectRequest
не идеален: в конце вы должны ожидать JSON
(см. Response.Listener<JSONObject>
). ResponseListener
? Я более или менее скомпилировал множество решений в большом родовом классе, чтобы иметь решение для всей проблемы, которую я цитировал.
/**
* Created by laurentmeyer on 25/07/15.
*/
public class GenericRequest<T> extends JsonRequest<T> {
private final Gson gson = new Gson();
private final Class<T> clazz;
private final Map<String, String> headers;
// Used for request which do not return anything from the server
private boolean muteRequest = false;
/**
* Basically, this is the constructor which is called by the others.
* It allows you to send an object of type A to the server and expect a JSON representing a object of type B.
* The problem with the #JsonObjectRequest is that you expect a JSON at the end.
* We can do better than that, we can directly receive our POJO.
* That's what this class does.
*
* @param method: HTTP Method
* @param classtype: Classtype to parse the JSON coming from the server
* @param url: url to be called
* @param requestBody: The body being sent
* @param listener: Listener of the request
* @param errorListener: Error handler of the request
* @param headers: Added headers
*/
private GenericRequest(int method, Class<T> classtype, String url, String requestBody,
Response.Listener<T> listener, Response.ErrorListener errorListener, Map<String, String> headers) {
super(method, url, requestBody, listener,
errorListener);
clazz = classtype;
this.headers = headers;
configureRequest();
}
/**
* Method to be called if you want to send some objects to your server via body in JSON of the request (with headers and not muted)
*
* @param method: HTTP Method
* @param url: URL to be called
* @param classtype: Classtype to parse the JSON returned from the server
* @param toBeSent: Object which will be transformed in JSON via Gson and sent to the server
* @param listener: Listener of the request
* @param errorListener: Error handler of the request
* @param headers: Added headers
*/
public GenericRequest(int method, String url, Class<T> classtype, Object toBeSent,
Response.Listener<T> listener, Response.ErrorListener errorListener, Map<String, String> headers) {
this(method, classtype, url, new Gson().toJson(toBeSent), listener,
errorListener, headers);
}
/**
* Method to be called if you want to send some objects to your server via body in JSON of the request (without header and not muted)
*
* @param method: HTTP Method
* @param url: URL to be called
* @param classtype: Classtype to parse the JSON returned from the server
* @param toBeSent: Object which will be transformed in JSON via Gson and sent to the server
* @param listener: Listener of the request
* @param errorListener: Error handler of the request
*/
public GenericRequest(int method, String url, Class<T> classtype, Object toBeSent,
Response.Listener<T> listener, Response.ErrorListener errorListener) {
this(method, classtype, url, new Gson().toJson(toBeSent), listener,
errorListener, new HashMap<String, String>());
}
/**
* Method to be called if you want to send something to the server but not with a JSON, just with a defined String (without header and not muted)
*
* @param method: HTTP Method
* @param url: URL to be called
* @param classtype: Classtype to parse the JSON returned from the server
* @param requestBody: String to be sent to the server
* @param listener: Listener of the request
* @param errorListener: Error handler of the request
*/
public GenericRequest(int method, String url, Class<T> classtype, String requestBody,
Response.Listener<T> listener, Response.ErrorListener errorListener) {
this(method, classtype, url, requestBody, listener,
errorListener, new HashMap<String, String>());
}
/**
* Method to be called if you want to GET something from the server and receive the POJO directly after the call (no JSON). (Without header)
*
* @param url: URL to be called
* @param classtype: Classtype to parse the JSON returned from the server
* @param listener: Listener of the request
* @param errorListener: Error handler of the request
*/
public GenericRequest(String url, Class<T> classtype, Response.Listener<T> listener, Response.ErrorListener errorListener) {
this(Request.Method.GET, url, classtype, "", listener, errorListener);
}
/**
* Method to be called if you want to GET something from the server and receive the POJO directly after the call (no JSON). (With headers)
*
* @param url: URL to be called
* @param classtype: Classtype to parse the JSON returned from the server
* @param listener: Listener of the request
* @param errorListener: Error handler of the request
* @param headers: Added headers
*/
public GenericRequest(String url, Class<T> classtype, Response.Listener<T> listener, Response.ErrorListener errorListener, Map<String, String> headers) {
this(Request.Method.GET, classtype, url, "", listener, errorListener, headers);
}
/**
* Method to be called if you want to send some objects to your server via body in JSON of the request (with headers and muted)
*
* @param method: HTTP Method
* @param url: URL to be called
* @param classtype: Classtype to parse the JSON returned from the server
* @param toBeSent: Object which will be transformed in JSON via Gson and sent to the server
* @param listener: Listener of the request
* @param errorListener: Error handler of the request
* @param headers: Added headers
* @param mute: Muted (put it to true, to make sense)
*/
public GenericRequest(int method, String url, Class<T> classtype, Object toBeSent,
Response.Listener<T> listener, Response.ErrorListener errorListener, Map<String, String> headers, boolean mute) {
this(method, classtype, url, new Gson().toJson(toBeSent), listener,
errorListener, headers);
this.muteRequest = mute;
}
/**
* Method to be called if you want to send some objects to your server via body in JSON of the request (without header and muted)
*
* @param method: HTTP Method
* @param url: URL to be called
* @param classtype: Classtype to parse the JSON returned from the server
* @param toBeSent: Object which will be transformed in JSON via Gson and sent to the server
* @param listener: Listener of the request
* @param errorListener: Error handler of the request
* @param mute: Muted (put it to true, to make sense)
*/
public GenericRequest(int method, String url, Class<T> classtype, Object toBeSent,
Response.Listener<T> listener, Response.ErrorListener errorListener, boolean mute) {
this(method, classtype, url, new Gson().toJson(toBeSent), listener,
errorListener, new HashMap<String, String>());
this.muteRequest = mute;
}
/**
* Method to be called if you want to send something to the server but not with a JSON, just with a defined String (without header and not muted)
*
* @param method: HTTP Method
* @param url: URL to be called
* @param classtype: Classtype to parse the JSON returned from the server
* @param requestBody: String to be sent to the server
* @param listener: Listener of the request
* @param errorListener: Error handler of the request
* @param mute: Muted (put it to true, to make sense)
*/
public GenericRequest(int method, String url, Class<T> classtype, String requestBody,
Response.Listener<T> listener, Response.ErrorListener errorListener, boolean mute) {
this(method, classtype, url, requestBody, listener,
errorListener, new HashMap<String, String>());
this.muteRequest = mute;
}
@Override
protected Response<T> parseNetworkResponse(NetworkResponse response) {
// The magic of the mute request happens here
if (muteRequest) {
if (response.statusCode >= 200 && response.statusCode <= 299) {
// If the status is correct, we return a success but with a null object, because the server didn't return anything
return Response.success(null, HttpHeaderParser.parseCacheHeaders(response));
}
} else {
try {
// If it's not muted; we just need to create our POJO from the returned JSON and handle correctly the errors
String json = new String(response.data, HttpHeaderParser.parseCharset(response.headers));
T parsedObject = gson.fromJson(json, clazz);
return Response.success(parsedObject, HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
} catch (JsonSyntaxException e) {
return Response.error(new ParseError(e));
}
}
return null;
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
return headers != null ? headers : super.getHeaders();
}
private void configureRequest() {
// Set retry policy
// Add headers, for auth for example
// ...
}
}
Это может показаться немного излишним, но это довольно классно иметь все эти конструкторы, потому что у вас есть все случаи:
(Основной конструктор не предназначался для непосредственного использования, хотя это, конечно, возможно).
Конечно, для того, чтобы это сработало, у вас должен быть Google GSON Lib ; просто добавьте:
compile 'com.google.code.gson:gson:x.y.z'
к вашим зависимостям (текущая версия 2.3.1
).
В то время как IronRuby быстро справится того, чтобы говорить с Вашей.NET dll (это не будет буквально никакой код вообще), от этого отказалась Microsoft, и это никогда не заставляло достаточно многочисленное сообщество разработчиков ПО с открытым исходным кодом сохранять его следующий за тем событием. Я не рекомендовал бы это в эти дни
Относительно решения COM, это может на самом деле быть хорошим способом пойти.
Вам не нужна библиотека RubyCOM - который позволяет другому вызову COM-объектов в код Ruby. Для загрузки COM-объектов из рубина Вам просто нужно win32ole
библиотека, которая стала частью стандартной библиотеки по рубину окон.
, Можно ли загрузить dll из COM, будет зависеть, если.NET dll была создана, чтобы быть 'Видимым Com'. Платформа.NET определяет ComVisibleAttribute
, который может быть применен или ко всему блоку или к определенным классам в рамках блока. Если это будет иметь значение true или для целого блока или для каких-либо классов, то dll уже будет вызываемым от COM без любого кода обертки.
Вот тест, который я сделал.
Создают новую.NET dll проект (библиотека классов). Вот класс в качестве примера, который я использовал:
using System;
using System.IO;
namespace ComLib
{
public class LogWriter
{
public void WriteLine( string line )
{
using( var log = new StreamWriter( File.OpenWrite( @"c:\log.file" ) ) )
{
log.WriteLine( line );
}
}
}
}
Теперь, в соответствии с проектом Visual Studio, существует каталог, названный Properties
, который содержит AssemblyInfo.cs
. В этом файле будет следующий
[assembly: ComVisible( false )]
Изменение ложь к истинному. Если Вы не хотите каждый класс в блоке, выставленном COM, то можно оставить его набором лжи в AssemblyInfo.cs
и вместо этого поместить его выше каждого класса, который Вы хотите выставить, как это:
[ComVisible( true )]
public class LogWriter ....
щелчок правой кнопкой Now по самому dll проекту, и из всплывающего меню, избранных 'свойств'. В списке разделов выберите Build
Scroll вниз и отметьте флажок 'Register for COM interop'. Теперь при компиляции этого DLL Visual Studio сделает необходимый материал для загрузки информации COM в реестр. Отметьте, находитесь ли Вы на перспективе, необходимо запустить VS как, администратор для этого для работы.
Теперь, когда это сделано, перекомпилируйте свой dll и затем создайте новый рубиновый файл.
В этом рубиновом файле, сделайте это:
require 'win32ole'
lib = WIN32OLE.new('[Solution name].ComLib.LogWriter')
lib.WriteLine('calling .net from ruby via COM, hooray!')
, Где [Название решения] должен быть заменен под названием решение, Вы просто создали (значение по умолчанию: "ClassLibrary1")
Ruby, что рубиновый файл, и престо! необходимо видеть, что текст записан в [1 110].
Одна проблема с этим решением состоит в том, что оно требует, чтобы.NET dll уже был Видимый Com, или если это не, у Вас есть способность перекомпилировать его. Если ни одна из этих вещей не верна, то Вам, вероятно, придется посмотреть на другие опции.
Удачи!
Если Вы хотите использовать 'нормальный' рубин (так как я не думаю, что IronRuby полностью выполняет RoR все же), Вы смогли идти через COM - т.е.
"Your Ruby Code" -> RubyCOM -> "COM-Callable Wrappers" -> "Your .NET objects"
, Это является немного замысловатым все же.
Редактирование: лучше основанная на COM опция в другом месте в ответах
Другая вещь - могло бы быть лучше думать об этом больше от точки Архитектуры Для обслуживания широкого круга запросов. Можно ли взять тот DLL.NET и выставить ли его как услуга?
Негласно, можно записать модули Ruby в C, таким образом, можно всегда писать interop, чтобы сделать то, в чем Вы нуждаетесь. Это ограничит Ваше развертывание на платформах Windows, хотя (я не попробовал Ruby-> Interop-> Моно)
, Вот презентация, которую я дал нескольким годам, назад названным Ruby для Разработчиков C# . Это немного датировано (Это было, прежде чем проект John Lam был свернут в IronRuby), но мог бы помочь немногому.
Хотя это - мертвый AFAIK проекта, можно найти предыдущее проект RubyCLR John Lam (кто теперь возглавляет IronRuby), интересный.
Если Вы интересуетесь ASP.NET MVC с IronRuby вместе, можно оказаться, что проверяете этот исходный код от Jimmy - , http://github.com/jschementi/ironrubymvc/tree/master
Обладает!
При использовании IronRuby (реализация Ruby основывалась на .NET), затем, это должно смочь. Если Вы уже используете .NET и хотите испытать Ruby затем, Вы могли бы хотеть изучить IronRuby.
За пределами IronRuby я не уверен. Я не использовал Ruby сам, таким образом, я не знаю, к каким видам вещей это способно.