Ruby может импортировать.NET dll?

Я знаю, что эта ветка довольно старая, но у меня была эта проблема, и я придумал классное решение, которое может быть очень полезным для многих, потому что оно исправляет / расширяет библиотеку Volley по многим аспектам.

Я заметил некоторые неработающие функции Volley:

  • Этот JSONObjectRequest не идеален: в конце вы должны ожидать JSON (см. Response.Listener<JSONObject> ).
  • Как насчет пустых ответов (только с статусом 200)?
  • Что мне делать, если я хочу непосредственно мой POJO из 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
         // ...
     }
 }

Это может показаться немного излишним, но это довольно классно иметь все эти конструкторы, потому что у вас есть все случаи:

(Основной конструктор не предназначался для непосредственного использования, хотя это, конечно, возможно).

  1. Запрос с ответом, обработанным POJO / заголовками вручную / POJO для отправки
  2. Запрос с ответом, обработанным POJO / POJO для отправки
  3. Запрос с ответом, обработанным POJO / String для отправки
  4. Запрос с ответом, обработанным POJO (GET)
  5. Запрос с ответом, обработанным POJO ( GET) / Заголовки вручную установлены
  6. Запрос без ответа (200 - Пустое тело) / Заголовки вручную установлены / POJO для отправки
  7. Запрос без ответа (200 - Пустое тело) / POJO Отправить
  8. Запрос без ответа (200 - Пустое тело) / String to Send

Конечно, для того, чтобы это сработало, у вас должен быть Google GSON Lib ; просто добавьте:

compile 'com.google.code.gson:gson:x.y.z'

к вашим зависимостям (текущая версия 2.3.1).

14
задан Chris Pietschmann 6 November 2008 в 21:38
поделиться

6 ответов

В то время как 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, или если это не, у Вас есть способность перекомпилировать его. Если ни одна из этих вещей не верна, то Вам, вероятно, придется посмотреть на другие опции.

Удачи!

32
ответ дан 1 December 2019 в 07:13
поделиться

Если Вы хотите использовать 'нормальный' рубин (так как я не думаю, что IronRuby полностью выполняет RoR все же), Вы смогли идти через COM - т.е.

"Your Ruby Code" -> RubyCOM -> "COM-Callable Wrappers" -> "Your .NET objects"

RubyCom

, Это является немного замысловатым все же.

Редактирование: лучше основанная на COM опция в другом месте в ответах

2
ответ дан 1 December 2019 в 07:13
поделиться

Другая вещь - могло бы быть лучше думать об этом больше от точки Архитектуры Для обслуживания широкого круга запросов. Можно ли взять тот DLL.NET и выставить ли его как услуга?

Негласно, можно записать модули Ruby в C, таким образом, можно всегда писать interop, чтобы сделать то, в чем Вы нуждаетесь. Это ограничит Ваше развертывание на платформах Windows, хотя (я не попробовал Ruby-> Interop-> Моно)

, Вот презентация, которую я дал нескольким годам, назад названным Ruby для Разработчиков C# . Это немного датировано (Это было, прежде чем проект John Lam был свернут в IronRuby), но мог бы помочь немногому.

1
ответ дан 1 December 2019 в 07:13
поделиться

Хотя это - мертвый AFAIK проекта, можно найти предыдущее проект RubyCLR John Lam (кто теперь возглавляет IronRuby), интересный.

0
ответ дан 1 December 2019 в 07:13
поделиться

Если Вы интересуетесь ASP.NET MVC с IronRuby вместе, можно оказаться, что проверяете этот исходный код от Jimmy - , http://github.com/jschementi/ironrubymvc/tree/master

Обладает!

0
ответ дан 1 December 2019 в 07:13
поделиться

При использовании IronRuby (реализация Ruby основывалась на .NET), затем, это должно смочь. Если Вы уже используете .NET и хотите испытать Ruby затем, Вы могли бы хотеть изучить IronRuby.

За пределами IronRuby я не уверен. Я не использовал Ruby сам, таким образом, я не знаю, к каким видам вещей это способно.

0
ответ дан 1 December 2019 в 07:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: