2012-06-09 2 views
-2

последний раз, когда я задал вопрос, здесь все предоставили некоторые отличные рекомендации по решению моей проблемы. Двигайтесь вперед во времени, а вот еще один. Я пытаюсь переделать небольшой помощник, который у меня есть, который проверяет URL-адрес и файлы против VirusTotal, чтобы получить некоторую базовую информацию. Код ниже работает достаточно хорошо, но блокирует пользовательский интерфейс. Мне сказали, что я должен смотреть в Rx, и мне нравится читать на нем, но, похоже, я не могу обернуть голову. Итак, теперь, когда возникает вопрос, как лучше всего разработать следующий код, чтобы он использовал Rx так, чтобы он был асинхронным и оставил мой пользовательский интерфейс, пока он это делает. VirusTotal также использует многоуровневый JSON для ответов, поэтому, если у кого-то есть хороший способ интегрировать это в это, это будет даже лучше.Synchronous VirusTotal code to Rx enabled асинхронный (и, возможно, некоторый разбор JSON)

class Virustotal 
{ 
    private string APIKey = "REMOVED"; 
    private string FileReportURL = "https://www.virustotal.com/vtapi/v2/file/report"; 
    private string URLReportURL = "http://www.virustotal.com/vtapi/v2/url/report"; 
    private string URLSubmitURL = "https://www.virustotal.com/vtapi/v2/url/scan"; 

    WebRequest theRequest; 
    HttpWebResponse theResponse; 
    ArrayList theQueryData; 

    public string GetFileReport(string checksum) // Gets latest report of file from VT using a hash (MD5/SHA1/SHA256) 
    { 
     this.WebPostRequest(this.FileReportURL); 
     this.Add("resource", checksum); 
     return this.GetResponse(); 
    } 

    public string GetURLReport(string url) // Gets latest report of URL from VT 
    { 
     this.WebPostRequest(this.URLReportURL); 
     this.Add("resource", url); 
     this.Add("scan", "1"); //Automatically submits to VT if no result found 
     return this.GetResponse(); 
    } 

    public string SubmitURL(string url) // Submits URL to VT for insertion to scanning queue 
    { 
     this.WebPostRequest(this.URLSubmitURL); 
     this.Add("url", url); 
     return this.GetResponse(); 
    } 

    public string SubmitFile() // Submits File to VT for insertion to scanning queue 
    { 
     // File Upload code needed 
     return this.GetResponse(); 
    } 

    private void WebPostRequest(string url) 
    { 
     theRequest = WebRequest.Create(url); 
     theRequest.Method = "POST"; 
     theQueryData = new ArrayList(); 
     this.Add("apikey", APIKey); 
    } 

    private void Add(string key, string value) 
    { 
     theQueryData.Add(String.Format("{0}={1}", key, Uri.EscapeDataString(value))); 
    } 

    private string GetResponse() 
    { 
     // Set the encoding type 
     theRequest.ContentType="application/x-www-form-urlencoded"; 

     // Build a string containing all the parameters 
     string Parameters = String.Join("&",(String[]) theQueryData.ToArray(typeof(string))); 
     theRequest.ContentLength = Parameters.Length; 

     // We write the parameters into the request 
     StreamWriter sw = new StreamWriter(theRequest.GetRequestStream()); 
     sw.Write(Parameters); 
     sw.Close(); 

     // Execute the query 
     theResponse = (HttpWebResponse)theRequest.GetResponse(); 
     StreamReader sr = new StreamReader(theResponse.GetResponseStream()); 
     return sr.ReadToEnd(); 
    } 
} 
+0

Кажется, никто не доволен тем, что я написал в качестве своего вопроса. Моя проблема в том, что я искал онлайн, а также в единственной книге о Rx, о которой я знаю о том, как это сделать. Я ничего не придумываю, и я надеялся, что сообщество SO поможет мне, а не просто голосует за мой вопрос. – lordzero

ответ

1

Ваш код плохо написан, что делает его сложнее сделать его асинхронным - в первую очередь тремя переменными уровня класса. При кодировании в Rx вы хотите думать «функциональное программирование», а не «ООП» - поэтому нет переменных уровня класса.

Итак, что я сделал это - я переделал метод GetResponse инкапсулировать все государства в один вызов - и я сделал это вернуть IObservable<string>, а не просто string.

Общественные функции теперь могут быть записаны следующим образом:

public IObservable<string> GetFileReport(string checksum) 
{ 
    return this.GetResponse(this.FileReportURL, 
     new Dictionary<string, string>() { { "resource", checksum }, }); 
} 

public IObservable<string> GetURLReport(string url) 
{ 
    return this.GetResponse(this.URLReportURL, 
     new Dictionary<string, string>() 
      { { "resource", url }, { "scan", "1" }, }); 
} 

public IObservable<string> SubmitURL(string url) 
{ 
    return this.GetResponse(this.URLSubmitURL, 
     new Dictionary<string, string>() { { "url", url }, }); 
} 

public IObservable<string> SubmitFile() 
{ 
    return this.GetResponse("UNKNOWNURL", new Dictionary<string, string>()); 
} 

GetResponse И выглядит следующим образом:

private IObservable<string> GetResponse(
    string url, 
    Dictionary<string, string> theQueryData) 
{ 
    return Observable.Start(() => 
    { 
     var theRequest = WebRequest.Create(url); 
     theRequest.Method = "POST"; 
     theRequest.ContentType="application/x-www-form-urlencoded"; 

     theQueryData.Add("apikey", APIKey); 

     string Parameters = String.Join("&", 
      theQueryData.Select(x => 
       String.Format("{0}={1}", x.Key, x.Value))); 
     theRequest.ContentLength = Parameters.Length; 

     using (var sw = new StreamWriter(theRequest.GetRequestStream())) 
     { 
      sw.Write(Parameters); 
      sw.Close(); 
     } 

     using (var theResponse = (HttpWebResponse)theRequest.GetResponse()) 
     { 
      using (var sr = new StreamReader(theResponse.GetResponseStream())) 
      { 
       return sr.ReadToEnd(); 
      } 
     } 
    }); 
} 

Я на самом деле не проверял это - я не имею APIKEY для но они должны работать нормально. Дайте мне знать, как вы идете.

+1

Спасибо за помощь. Я не смогу проверить его на день или два, но я обязательно сообщу вам, как это происходит. Поскольку вы сказали, что мой код плохо написан (с которым я не согласен), что вы предлагаете мне сделать в будущем, чтобы сделать его лучше? – lordzero

+0

Ну, как я уже сказал в своем ответе - вам нужно думать более функционально и избегать удерживания состояния при выполнении служебных вызовов, подобных тем, которые заданы в вашем вопросе. Это будет хорошим началом. – Enigmativity

 Смежные вопросы

  • Нет связанных вопросов^_^