乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      通過谷歌服務(wù)安排郵寄活動

       Levy_X 2019-08-06

      簡介

      交易者可能希望安排一次郵寄活動,以維持與其他交易者、訂戶、客戶或朋友的業(yè)務(wù)關(guān)系。此外,可能需要發(fā)送截圖、日志或報告。這些任務(wù)可能不是最經(jīng)常出現(xiàn)的任務(wù),但是擁有這樣的特性顯然是一個優(yōu)勢。在這里使用方便的MQL工具絕對是困難的,甚至是完全不可能的。在本文的最后,我們將回到使用專門的MQL工具來解決此任務(wù)的問題。在此之前,我們將使用MQL和C#的組合。這將使我們相對容易地編寫必要的代碼并將其連接到終端,此外,它還將設(shè)置一個與此連接相關(guān)的非常有趣的挑戰(zhàn)。

      本文面向初學(xué)者和中層開發(fā)人員,他們希望加深他們對編寫庫的知識,并將它們與終端集成,同時更加熟悉Google服務(wù)。

      設(shè)置任務(wù)

      現(xiàn)在,讓我們更準(zhǔn)確地定義我們將要做什么,有一個可更新的聯(lián)系人列表,允許用戶向列表中的任何聯(lián)系人發(fā)送一次或多次帶有附件的電子郵件。需要考慮的事項:

      • 列表中的某些聯(lián)系人可能沒有地址,或者地址不正確。此外,可能有多個地址。
      • 可以更改列表-可以添加或刪除聯(lián)系人。
      • 聯(lián)系人可以重復(fù)。
      • 它們也可能被排除在郵寄活動之外,而留在列表中。換句話說,聯(lián)系人的活動應(yīng)該是可調(diào)整的。
      • 此外,列表中肯定會包含與相關(guān)任務(wù)無關(guān)的聯(lián)系人。

      實施列表管理是最明顯的任務(wù)。我們這里有什么選擇?

      1. HDD 數(shù)據(jù)庫或 CSV 文件不方便且不夠可靠。它并不總是可用的,可能需要一個額外的軟件來管理這樣的存儲。
      2. 一個特殊網(wǎng)站的數(shù)據(jù)庫,有一個Joomla類型的CMS,這是一個很好的解決方案。數(shù)據(jù)受到保護(hù),可以從任何地方訪問。此外,電子郵件可以很容易地從網(wǎng)站發(fā)送。然而,也有一個顯著的缺點。與此類網(wǎng)站交互需要一個特殊的附加組件,這樣的附加組件可能非常大,并且充滿了安全漏洞。換句話說,這里必須有可靠的基礎(chǔ)設(shè)施。
      3. 使用現(xiàn)成的 Google 服務(wù)。在那里,您可以安全地存儲和管理聯(lián)系人,以及從不同的設(shè)備訪問他們。尤其是,您可以形成各種列表(組)并發(fā)送電子郵件。這就是我們舒適工作所需要的一切,所以我們堅持這個選擇。

      與 Google 交互有大量的文檔記錄,例如這里。要開始使用Google,請注冊一個帳戶并在那里創(chuàng)建聯(lián)系人列表,該列表應(yīng)包含我們要向其發(fā)送電子郵件的聯(lián)系人。在“聯(lián)系人”中,創(chuàng)建具有特定名稱的組,例如“Forex”,并將所選聯(lián)系人添加到該組中。每個聯(lián)系人都可以保存多個數(shù)據(jù)以備以后使用。不幸的是,如果用戶仍然需要一個額外的數(shù)據(jù)字段,則無法創(chuàng)建它,這不會造成不便,因為有很多數(shù)據(jù)字段可用,稍后我將演示如何使用它們,

      現(xiàn)在是時候開始主要任務(wù)了。

      谷歌方面的準(zhǔn)備工作

      假設(shè)我們已經(jīng)有一個谷歌帳戶,使用谷歌“開發(fā)控制臺”恢復(fù)項目開發(fā)。在這里您可以詳細(xì)了解如何使用控制臺和開發(fā)項目,當(dāng)然,上面的鏈接將介紹另一個項目。我們的項目需要一個名字,讓它名為 ' WorkWithPeople'。我們還需要其他服務(wù),在此階段,啟用以下選項:

      • People API
      • Gmail API

      第一個提供了對聯(lián)系人列表的訪問(實際上,它也提供了對其他事物的訪問,但我們只需要列表)。有另一個用于訪問聯(lián)系人列表的服務(wù)-Contacts API,但目前不建議使用,因此我們不注意它。

      顧名思義,第二個服務(wù)提供對郵件的訪問。

      啟用服務(wù)并獲取授予應(yīng)用程序訪問它們的密鑰。不需要寫下來或者記住,以 json 格式下載附件,其中包含訪問 Google 資源所需的所有數(shù)據(jù),包括這些密鑰。將文件保存在磁盤上,也許可以給它一個更有意義的名稱。在我的例子中,它被稱為“WorkwithPeople_gmail.json”。這就完成了與谷歌的直接操作,我們已經(jīng)創(chuàng)建了帳戶、聯(lián)系人列表和項目,并獲得了訪問文件。

      現(xiàn)在,讓我們繼續(xù)在 VS 2017 工作。

      項目和開發(fā)包

      打開 VS 2017并創(chuàng)建一個標(biāo)準(zhǔn)Class Library(.NET Framework)項目。以任何可記憶的方式命名它(在我的例子中,它與Google項目名稱“WorkwithPeople”一致,盡管這不是必須的)。使用NuGet立即安裝其他軟件包:

      • Google.Apis
      • Google.Apis.People.v1
      • Google.Apis.PeopleService.v1
      • Google.Apis.Gmail.v1
      • MimeKit

        在安裝過程中,Nuget提供安裝相關(guān)軟件包的服務(wù),要對此表示同意。在我們的例子中,該項目接收谷歌的軟件包,用于處理聯(lián)系人和管理電子郵件。現(xiàn)在我們準(zhǔn)備好開發(fā)代碼了。

        訪問聯(lián)系人

        讓我們從輔助類開始,如果我們考慮到某個谷歌聯(lián)系人所包含的數(shù)據(jù)量,那么很明顯,我們的任務(wù)不需要它的主要部分,我們需要一個聯(lián)系人姓名和地址發(fā)送電子郵件。事實上,我們還需要來自另一個欄位的數(shù)據(jù),但稍后會討論更多。

        相應(yīng)的類可以如下所示:

        namespace WorkWithPeople {    internal sealed class OneContact     {         public OneContact(string n, string e)         {             this.Name = n;             this.Email = e;         }         public string Name { get; set; }         public string Email { get; set; }     } }

        有兩個“字符串”類型的屬性存儲聯(lián)系人姓名和地址,以及一個簡單的構(gòu)造函數(shù),其中包含兩個參數(shù)來初始化它們,沒有實現(xiàn)另外的檢查,它們將在其它地方進(jìn)行。

        讀取聯(lián)系人列表時會創(chuàng)建簡單元素列表。這允許根據(jù)這個新構(gòu)建的列表的數(shù)據(jù)進(jìn)行郵件活動。如果要更新列表,請刪除所有列表元素,然后重復(fù)從Google帳戶讀取和選擇數(shù)據(jù)的操作。

        還有另一個輔助類,聯(lián)系人列表可能包含無效的電子郵件地址,或者根本沒有地址,在發(fā)送電子郵件之前,我們需要確保地址正確無誤,讓我們開發(fā)新的輔助類來實現(xiàn)這一點:

        namespace WorkWithPeople
        {    
            internal static class ValidEmail
            {
                public stati cbool IsValidEmail(this string source) => !string.IsNullOrEmpty(source) && new System.ComponentModel.DataAnnotations.EmailAddressAttribute().IsValid(source);
            }
        }
        
        

        為了執(zhí)行檢查,我們使用可用的工具,盡管我們也可以使用正則表達(dá)式。為了便于進(jìn)一步使用,我們開發(fā)了代碼作為擴展方法。由于不難猜測,如果包含郵件地址的字符串通過檢查,則該方法返回true,否則返回false?,F(xiàn)在是時候轉(zhuǎn)到代碼的主要部分了。

        訪問和使用服務(wù)

        我們已經(jīng)創(chuàng)建了項目,獲取了密鑰,并下載了用于授權(quán)應(yīng)用程序的JSON文件。因此,讓我們創(chuàng)建一個新的類ContactsPeople并將適當(dāng)?shù)某绦蚣砑拥轿募校?/p>

        using System; using System.Collections.Generic; using System.Linq; using System.IO; using System.Net.Mail; using System.Text; using System.Threading; using System.Threading.Tasks; using Google.Apis.Auth.OAuth2; using Google.Apis.People.v1; using Google.Apis.Services; using Google.Apis.Util.Store; using Google.Apis.Http; using Google.Apis.PeopleService.v1; using Google.Apis.PeopleService.v1.Data; using Google.Apis.Gmail.v1; using Google.Apis.Gmail.v1.Data; namespace WorkWithPeople {     internal sealed class ContactsPeople     { public static string Applicationname { get; } = 'WorkWithPeople'; .....

        添加包含Google項目名稱的靜態(tài)屬性,此靜態(tài)屬性為只讀。

        將封閉字段和枚舉添加到類:

                private enum             PersonStatus
                {
                    Active,
                    Passive
                };
                private string           _groupsresourcename;
                private List<OneContact> _list = new List<OneContact>();
                private UserCredential   _credential;
                private PeopleService    _pservice;
                private GmailService     _gservice;
        

        枚舉用于將聯(lián)系人標(biāo)記為“主動”(接收電子郵件)和“被動”(不接收電子郵件)。其他封閉字段:

        • _groupsresourcename. 與“聯(lián)系人”中創(chuàng)建的組相對應(yīng)的Google資源名稱,(在我們的例子中,所選的組名是“Forex”)。
        • _list. 郵寄活動要應(yīng)用到的聯(lián)系人列表。
        • _credential. 應(yīng)用 'powers'.
        • _pservice, _gservice. 用于處理聯(lián)系人和郵件的服務(wù)。

        讓我們編寫主要工作函數(shù)的代碼:

                publicint WorkWithGoogle(string credentialfile,                                    string user,                                    string filedatastore,                                    string groupname,                                    string subject,                                    string body,                                    bool   isHtml,                                    List<string> attach = null)         { ...

        其參數(shù)是:

        • credentialfile. 訪問包含用于訪問服務(wù)的所有數(shù)據(jù)的JSON文件的名稱和路徑,它以前是從谷歌賬戶下載的。
        • user. 谷歌帳戶名 - xxxxx@gmail.com地址。
        • filedatastore. 輔助文件夾的名稱-用戶PC上的存儲(可以是任意的)。該文件夾是在 AppData(%APPDATA%)中創(chuàng)建的,其中包含包含附加訪問數(shù)據(jù)的文件。
        • groupname. 我們創(chuàng)建的郵寄活動的聯(lián)系人組的名稱,在我們的例子中,它是“Forex”。
        • subject, body, isHtml. 郵件主題和文本,以及是否以HTML格式編寫。
        • attach. 附件列表。

        返回值 - 已發(fā)送電子郵件的數(shù)量。開始編寫函數(shù)代碼:

                    if (!File.Exists(credentialfile))
                        throw (new FileNotFoundException('Not found: '   credentialfile));
                    using (var stream = new FileStream(credentialfile, FileMode.Open, FileAccess.Read))
                    {
                        if (_credential == null) {
                            _credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
                                GoogleClientSecrets.Load(stream).Secrets,
                                new[]
                                {
                                    GmailService.Scope.GmailSend,
                                    PeopleService.Scope.ContactsReadonly
                                },
                                user,
                                CancellationToken.None,
                                new FileDataStore(filedatastore)).Result;
                                CreateServicies();
                        }
                        else if (_credential.Token.IsExpired(Google.Apis.Util.SystemClock.Default)) {
                            bool refreshResult = _credential.RefreshTokenAsync(CancellationToken.None).Result;
                            _list.Clear();
                            if (!refreshResult) return 0;   
                            CreateServicies();
                        }
                        
                    }// using (var stream = new FileStream(credentialfile, FileMode.Open, FileAccess.Read))
        

        請注意定義應(yīng)請求服務(wù)的訪問權(quán)限的字符串?dāng)?shù)組:

        • GmailService.Scope.GmailSend. 這是發(fā)送電子郵件的權(quán)限。
        • PeopleService.Scope.ContactsReadonly. 以只讀模式訪問聯(lián)系人。

        另外,注意調(diào)用 GoogleWebAuthorizationBroker.AuthorizeAsync. 它的名稱表明調(diào)用是異步執(zhí)行的。

        請注意,如果以前收到的令牌已過期,代碼將更新它并從以前形成的 _list 中刪除所有對象。

        輔助的 CreateServicies() 函數(shù)創(chuàng)建并初始化必要的對象:

                private void         CreateServicies()         {             _pservice = new PeopleService(new BaseClientService.Initializer()             {                 HttpClientInitializer = _credential,                 ApplicationName = Applicationname             });             _gservice = new GmailService(new BaseClientService.Initializer()             {                 HttpClientInitializer = _credential,                 ApplicationName = Applicationname             });         }

        如我們所見,在執(zhí)行上面顯示的代碼段后,我們可以訪問必要的服務(wù):

         - 使用JSON數(shù)據(jù)文件,我們首先請求“powers”,并將它們保存在_credential字段中。然后我們調(diào)用將“power”和項目名稱字段傳遞給它們的服務(wù)構(gòu)造函數(shù)作為初始化列表。

        現(xiàn)在是獲取為郵寄活動選擇的組的聯(lián)系人列表的時間:

                    try {
                          if (_list.Count == 0)
                            GetPeople(_pservice, null, groupname);                     
                    }
                    catch (Exception ex) {
                        ex.Data.Add('call GetPeople: ', ex.Message);
                        throw;
                    }
        #if DEBUG
                    int i = 1;
                    foreach (var nm in _list) {
                        Console.WriteLine('{0} {1} {2}', i  , nm.Name, nm.Email);
                    }
        #endif
                    if (_list.Count == 0) {
                        Console.WriteLine('Sorry, List is empty...');
                        return 0;
                    }
        

        GetPeople(…)函數(shù)(稍后描述)是要填充存儲聯(lián)系人的 _list。此函數(shù)用作異常源,因此其塊包裝在try代碼塊中。在已連接的程序集中未檢測到異常類型,因此catch塊以最一般的形式寫入。換句話說,我們不必在這里包括所有可能發(fā)生的事件,這樣就不會丟失用于調(diào)試的有價值的數(shù)據(jù)。因此,向異常添加您認(rèn)為必要的數(shù)據(jù)并重新激活它。

        請記住,只有當(dāng)它為空時(即當(dāng)它接收到新令牌或更新舊令牌時),才會更新_ list。

        下一個塊僅對調(diào)試版本執(zhí)行. 整個形成的列表只顯示在控制臺中。

        最后一塊很明顯,如果名單仍然空白,則進(jìn)一步的工作沒有點,并被相應(yīng)的信息所阻止。

        該函數(shù)以形成一個傳出電子郵件并進(jìn)行郵件活動而結(jié)束:

                    using (MailMessage mail = new MailMessage             {                 Subject = subject,                 Body = body,                 IsBodyHtml = isHtml             })  // MailMessage mail = new MailMessage             {                 if (attach != null)                 {                     foreach (var path in attach)                         mail.Attachments.Add(new Attachment(path));                 } //  if (attach != null)                 foreach (var nm in _list)                     mail.To.Add(new MailAddress(nm.Email, nm.Name));                 try                 {                     SendOneEmail(_gservice, mail);                 }                 catch (Exception ex)                 {                     ex.Data.Add('call SendOneEmail: ', ex.Message);                     throw;                 }             }// using (MailMessage mail = new MailMessage

        此處創(chuàng)建了MailMessage庫類的實例。接下來是它隨后的初始化和填充字段。如果有附件,則添加附件列表。最后,形成前一階段獲得的郵件列表。

        郵寄由SendOneEmail(…)稍后描述的函數(shù)執(zhí)行。就像GetPeople(…)函數(shù)一樣,它也可能成為異常源。因此,它的調(diào)用也被包裝在try代碼中,而在catch中的處理也是類似的。

        此時,WorkWithGoogle(…) 主函數(shù)的工作被認(rèn)為是完成的,它返回_list.Count值,假設(shè)電子郵件消息從列表發(fā)送到每個聯(lián)系人。

        填寫聯(lián)系人列表

        獲取訪問權(quán)限后,準(zhǔn)備好填寫_list,這是通過以下函數(shù)完成的:

                private void         GetPeople(PeopleService service, string pageToken, string groupName)
                {
                   ...
        

        其參數(shù)是:

        • service. 指向先前創(chuàng)建的Google聯(lián)系人訪問類的鏈接。
        • pageToken. 可能有多個聯(lián)系人。此參數(shù)告訴開發(fā)人員聯(lián)系人列表占用多個頁面。
        • groupName. 我們感興趣的聯(lián)系人組的名稱,

        第一次使用 pageToken = NULL 調(diào)用函數(shù),如果對 Google 的請求隨后返回值不同于NULL的令牌,則遞歸調(diào)用該函數(shù)。

                    if (string.IsNullOrEmpty(_groupsresourcename))             {                 ContactGroupsResource groupsResource = new ContactGroupsResource(service);                 ContactGroupsResource.ListRequest listRequest = groupsResource.List();                 ListContactGroupsResponse response = listRequest.Execute();                 _groupsresourcename = (from gr in response.ContactGroups                                        where string.Equals(groupName.ToUpperInvariant(), gr.FormattedName.ToUpperInvariant())                                        select gr.ResourceName).Single();                 if (string.IsNullOrEmpty(_groupsresourcename))                     throw (new MissingFieldException($'Can't find GroupName: {groupName}'));             }// if (string.IsNullOrEmpty(_groupsresourcename))

        我們需要通過組名找到一個資源名,為此,請求所有資源的列表,并在簡單的 lambda 表達(dá)式中找到所需的資源。請注意,應(yīng)該只有一個具有所需名稱的資源,如果在工作期間找不到資源,則啟用異常。

        Google.Apis.PeopleService.v1.PeopleResource.ConnectionsResource.ListRequest peopleRequest =
                        new Google.Apis.PeopleService.v1.PeopleResource.ConnectionsResource.ListRequest(service, 'people/me')
                        {
                            PersonFields = 'names,emailAddresses,memberships,biographies'
                        };
                    if (pageToken != null) {
                        peopleRequest.PageToken = pageToken;
                    }
        
        

        讓我們構(gòu)造對谷歌的請求,以獲得必要的列表,為此,請指定我們感興趣的谷歌聯(lián)系人數(shù)據(jù)中的字段:

        • names, emailAddresses. 用于創(chuàng)建 OneContact 類的實例.
        • memberships. 檢查聯(lián)系人是否屬于我們組。
        • biographies. 選擇此字段是為了管理聯(lián)系人活動,盡管它是為了存儲聯(lián)系人的個人簡歷而設(shè)計的。為了使聯(lián)系人被識別為活動聯(lián)系人并向其地址發(fā)送電子郵件,字段必須以一開頭。在任何其他情況下,即使聯(lián)系人位于必要的組中,也被認(rèn)為是被動的和忽略的。沒有必要為此使用這個特定的字段,在我們的例子中,它的選擇可能是因為它的使用相對較少。這對于用戶管理郵件活動非常方便,因為它允許“啟用/禁用”某些聯(lián)系人。

        最后,提出請求:

                    var request = peopleRequest.Execute();             var list1 = from person in request.Connections                      where person.Biographies != null                      from mem in person.Memberships                      where string.Equals(_groupsresourcename, mem.ContactGroupMembership.ContactGroupResourceName) &&                            PersonActive(person.Biographies.FirstOrDefault()?.Value) == PersonStatus.Active                      let name = person.Names.First().DisplayName                      orderby name                      let email = person.EmailAddresses?.FirstOrDefault(p => p.Value.IsValidEmail())?.Value                      where !string.IsNullOrEmpty(email)                      select new OneContact(name, email);             _list.AddRange(list1);             if (request.NextPageToken != null) {                 GetPeople(service, request.NextPageToken, groupName);             }         }//void GetPeople(PeopleService service, string pageToken, string groupName)

        發(fā)出請求并對 lambda 表達(dá)式中的必要數(shù)據(jù)進(jìn)行排序,它看起來相當(dāng)笨重,但實際上相當(dāng)簡單。一個聯(lián)系人應(yīng)該有一個非零的個人簡歷,在正確的組中,是一個活躍的聯(lián)系人,并有一個正確的地址。讓我們在這里展示通過“biographies”字段內(nèi)容定義單個聯(lián)系人的“active/passive”狀態(tài)的功能:

                private PersonStatus PersonActive(string value)
                {
                    try {
                        switch (Int32.Parse(value))
                        {
                            case 1:
                                return PersonStatus.Active;
                            default:
                                return PersonStatus.Passive;
                        }
                    }
                    catch (FormatException)   { return PersonStatus.Passive; }
                    catch (OverflowException) { return PersonStatus.Passive; }
                }//PersonStatus PersonActive(string value)
        

        這是項目中唯一一個不尋求重新啟用異常(嘗試在現(xiàn)場處理其中一些異常)的函數(shù)。

        我們快完成了!將獲得的列表添加到_list中,如果沒有讀取所有聯(lián)系人,則使用新的標(biāo)記值遞歸調(diào)用函數(shù)。

        發(fā)送電子郵件

        這由以下輔助函數(shù)執(zhí)行:

                private void SendOneEmail(GmailService service, MailMessage mail)         {             MimeKit.MimeMessage mimeMessage = MimeKit.MimeMessage.CreateFromMailMessage(mail);             var encodedText = Base64UrlEncode(mimeMessage.ToString());             var message = new Message { Raw = encodedText };             var request = service.Users.Messages.Send(message, 'me').Execute();         }//  bool SendOneEmail(GmailService service, MailMessage mail)

          它的調(diào)用如上所述,這個簡單函數(shù)的目的是為發(fā)送和執(zhí)行郵件活動準(zhǔn)備電子郵件,此外,該函數(shù)還具有所有“繁重”的準(zhǔn)備工作。不幸的是,Google不接受MailMessage類形式的數(shù)據(jù),因此,以可接受的形式準(zhǔn)備數(shù)據(jù)并對其進(jìn)行編碼。MimeKit程序集包括執(zhí)行編碼的工具。但是,我相信使用一個我們可以使用的簡單函數(shù)要容易得多,我不會在這里展示它,因為它很簡單。請注意在Service.Users.Messages.Send調(diào)用中的string類型的userId,它等于“me”的特殊值,允許Google訪問您的帳戶以獲取發(fā)送者數(shù)據(jù)。

          這就結(jié)束了對ContactsPeople類的分析,其余的函數(shù)是輔助的,因此沒有必要停留在它們上面。

          終端連接器

          唯一剩下的問題是將(未完成的)組件連接到終端。乍一看,任務(wù)很簡單,定義幾個靜態(tài)方法,編譯項目并將其復(fù)制到終端的庫文件夾中。從MQL代碼調(diào)用程序集的靜態(tài)方法。但我們究竟應(yīng)該復(fù)制什么呢?有一個dll庫形式的程序集。在我們的工作中,NuGet還下載了十幾個程序集。有一個JSON文件存儲用于訪問Google的數(shù)據(jù)。讓我們嘗試將整個集合復(fù)制到“Libraries”文件夾。創(chuàng)建一個基本的MQL腳本(這里沒有附加代碼的意義),然后嘗試從程序集調(diào)用靜態(tài)方法。異常!沒有找到 Google.Apis.dll,這是一個非常令人不快的驚喜,這意味著CLR無法找到所需的程序集,盡管它與我們的主程序集位于同一文件夾中。為什么會這樣?不值得詳細(xì)研究這里的情況。所有對細(xì)節(jié)感興趣的人都可以在 Richter 的名著中找到它們(在關(guān)于尋找私有程序庫的章節(jié)中)。

          已經(jīng)有許多與 MetaTrader 一起工作的功能完備的.NET應(yīng)用程序的例子,在那里也發(fā)生了這樣的問題。它們是怎么解決的呢?在這里通過在.NET應(yīng)用程序和MQL程序之間創(chuàng)建通道解決了這個問題,而這里使用了一種基于事件的模式。我可以建議使用類似的方法,使用命令行將所需數(shù)據(jù)從MQL程序傳遞到.NET應(yīng)用程序。

          但值得考慮的是更“優(yōu)雅”,簡單和普遍的解決方案。我的意思是使用 AppDomain.AssemblyResolve事件管理程序集下載。當(dāng)執(zhí)行要求無法按名稱綁定程序集時,會發(fā)生此事件。在這種情況下,事件處理程序可以從另一個文件夾(擁有處理程序知道的地址)加載和返回程序集。因此,在這里提出一個相當(dāng)漂亮的解決方案:

          1. 在 “Libraries” 文件夾中創(chuàng)建一個具有不同名稱的文件夾(在我的例子中,它是“WorkWithPeople”),
          2. 將其方法導(dǎo)入到帶有MQL的文件中的程序集復(fù)制到 “Libraries”文件夾。
          3. 所有其他項目程序集,包括包含訪問Google服務(wù)數(shù)據(jù)的JSON文件,都被復(fù)制到“WorkWithPeople”文件夾中。
          4. 讓libraries文件夾中的主程序集知道它應(yīng)該在哪里查找其他程序集 - “WorkWithPeople”文件夾的完整路徑。

          這樣,我們就得到了一個可行的解決方案,而不會把“Libraries”文件夾弄亂。剩下的就是在代碼中實現(xiàn)決策了。

          控制類

          讓我們創(chuàng)建一個靜態(tài)類

              public static class Run
              {
          
                  static Run() {
                      AppDomain.CurrentDomain.AssemblyResolve  = ResolveAssembly;
                  }// Run()
          

          并向其中添加事件處理程序,以便它盡快出現(xiàn)在處理程序鏈中。讓我們定義處理程序本身:

                  static Assembly ResolveAssembly(object sender, ResolveEventArgs args) {             String dllName = new AssemblyName(args.Name).Name '.dll';             return Assembly.LoadFile(Path.Combine(_path, dllName) );         }// static Assembly ResolveAssembly(object sender, ResolveEventArgs args)

          現(xiàn)在,每當(dāng)檢測到程序集時,都會調(diào)用此處理程序。其目標(biāo)是下載并返回程序集,該程序集結(jié)合了_path變量和計算名稱之間的路徑?,F(xiàn)在,只有處理程序找不到程序集時才會出現(xiàn)異常。

          初始化函數(shù)如下:

          WorkwithPeoplepublic static void Initialize(string Path, string GoogleGroup, string AdminEmail, string Storage)
                  {
                      if (string.IsNullOrEmpty(Path) ||
                          string.IsNullOrEmpty(GoogleGroup) ||
                          string.IsNullOrEmpty(AdminEmail) ||
                          string.IsNullOrEmpty(Storage)) throw (new MissingFieldException('Initialize: bad parameters'));
                      _group = GoogleGroup;
                      _user = AdminEmail;
                      _storage = Storage;
                      _path = Path;
                  }//  Initialize(string Path, string GoogleGroup, string AdminEmail, string Storage)
          
          

          在嘗試發(fā)送電子郵件之前,應(yīng)首先調(diào)用此函數(shù),其參數(shù)是:

          • Path. 處理程序查找程序集以及用于訪問Google的數(shù)據(jù)文件所在的路徑。
          • GoogleGroup. 用于郵寄的聯(lián)系人中的組的名稱。
          • AdminEmail. 帳戶名/郵件地址(xxx@google.com),代表該帳戶進(jìn)行郵件發(fā)送。
          • Storage. 存儲一些附加數(shù)據(jù)的輔助文件的名稱。

          所有描述的參數(shù)不應(yīng)為空字符串,否則將激活異常。

          為包含的文件創(chuàng)建一個列表和一個簡單的添加函數(shù):

          public static void AddAttachment (string attach) { _attachList.Add(attach);}

          該函數(shù)沒有錯誤檢查工具,因為它處理的是在 MetaTrader 環(huán)境中初步創(chuàng)建的屏幕截圖和其他文件。假設(shè)這是由終端中工作的控制工具完成的。

          讓我們馬上創(chuàng)建一個郵寄對象

          static ContactsPeople _cContactsPeople = new ContactsPeople();
          
          

          并通過調(diào)用函數(shù)來執(zhí)行:

          public static int DoWork(string subject, string body, bool isHtml = false) {             if (string.IsNullOrEmpty(body))                 throw (new MissingFieldException('Email body null or empty'));             int res = 0;             if (_attachList.Count > 0) {                 res = _cContactsPeople.WorkWithGoogle(Path.Combine(_path, 'WorkWithPeople_gmail.json'),                     _user,                     _storage,                     _group,                     subject,                     body,                     isHtml,                     _attachList);                 _attachList.Clear();             } else {                 res = _cContactsPeople.WorkWithGoogle(Path.Combine(_path, 'WorkWithPeople_gmail.json'),                     _user,                     _storage,                     _group,                     subject,                     body,                     isHtml);             }// if (_attachList.Count > 0) ... else ...             return res;         }// static int DoWork(string subject, string body, bool isHtml = false)

          輸入?yún)?shù)如下:

          • subject. 電子郵件主題。
          • body. 電子郵件文本。
          • isHtml. 電子郵件是否具有HTML格式。

          有兩個選項可以調(diào)用_cContactsPeople.WorkWithGoogle,具體取決于電子郵件功能附件。調(diào)用的第一個參數(shù)特別有趣:

          Path.Combine(_path, 'WorkWithPeople_gmail.json')

          這是包含用于訪問Google服務(wù)的數(shù)據(jù)的文件的完整路徑。

          DoWork(…)函數(shù)返回已發(fā)送電子郵件的數(shù)量。

          除用于訪問Google的數(shù)據(jù)文件外,VS 2017的整個項目位于所附的google.zip檔案中。

          MetaTrader 方面的準(zhǔn)備工作

          程序集代碼已就緒,讓我們繼續(xù)到終端,在那里創(chuàng)建一個簡單的腳本??梢赃@樣編寫(跳過開頭部分代碼):

          #import 'WorkWithPeople.dll' void OnStart()   {    string scr = 'scr.gif';    string fl = TerminalInfoString(TERMINAL_DATA_PATH) '\\MQL5\\Files\\';    ChartScreenShot(0, scr, 800, 600);      Run::Initialize('e:\\Forex\\RoboForex MT5 Demo\\MQL5\\Libraries\\WorkWithPeople\\' ,'Forex' ,'ХХХХХХ@gmail.com' ,'WorkWithPeople' );    Run::AddAttachment(fl scr);    int res = Run::DoWork('some subj' , 'Very big body' , false );    Print('result: ', res);     }

          代碼非常清楚。導(dǎo)入程序集。我們要做的第一件事是初始化它,添加先前制作的屏幕截圖并執(zhí)行郵件發(fā)送。完整的代碼可以在附加文件 google_test1.mq5中找到。

          另一個例子是在M5上工作的指標(biāo),每次檢測到新燭形時都會發(fā)送帶有屏幕截圖的電子郵件:

          #import 'WorkWithPeople.dll'
          
          input string scr='scr.gif';
          
          string fp;
          
          int OnInit()
            {
             fp=TerminalInfoString(TERMINAL_DATA_PATH) '\\MQL5\\Files\\';
             Run::Initialize('e:\\Forex\\RoboForex MT5 Demo\\MQL5\\Libraries\\WorkWithPeople\\','Forex','0ndrei1960@gmail.com','WorkWithPeople');
          
             return(INIT_SUCCEEDED);
            }
          
          int OnCalculate(const int rates_total,
                          const int prev_calculated,
                          const datetime &time[],
                          const double &open[],
                          const double &high[],
                          const double &low[],
                          const double &close[],
                          const long &tick_volume[],
                          const long &volume[],
                          const int &spread[])
            {
             if(IsNewCandle()) 
               {
                ChartScreenShot(0,scr,800,600);
                Run::AddAttachment(fp scr);
                string body='Time: ' TimeToString(TimeLocal());
                int res=Run::DoWork('some subj',body,false);
                Print(body);
               }
             return(rates_total);  
            }
          
          

          指標(biāo)的完整代碼可以在所附 google_test2.mq5 文件中找到,它非常簡單,因此不需要進(jìn)一步的討論。

          結(jié)論

          讓我們看看結(jié)果,我們分析了使用谷歌聯(lián)系人與合作伙伴進(jìn)行交互,以及將程序集與終端集成的方法,使用戶可以避免將文件夾與不必要的文件混淆。匯編代碼的效率也值得一提,我們對這一問題的關(guān)注不夠,但可以提供一系列活動來解決這一問題:

          • 在谷歌中劃分授權(quán)和發(fā)送電子郵件的目標(biāo)。由計時器在單獨的線程中進(jìn)行授權(quán)。
          • 嘗試使用線程池發(fā)送電子郵件。
          • 使用異步工具對電子郵件附件進(jìn)行“大量”編碼。

          這并不意味著您應(yīng)該使用所有這些方法,但它們的使用可能會提高性能,并允許將生成的程序集作為單獨流程的一部分與MetaTrader一起單獨應(yīng)用。

          總之,讓我們回到使用MQL工具解決此任務(wù)的問題,有可能嗎?根據(jù)谷歌文檔,答案是肯定的,使用GET/POSTt請求可以獲得相同的結(jié)果,并提供適當(dāng)?shù)氖纠?。因此,可以使用常?guī)的WebRequest。這種方法的可行性仍然是一個爭論的問題,由于請求的數(shù)量非常多,因此很難編寫、調(diào)試和維護(hù)這樣的代碼。

          文章中使用的程序

           # 名稱
          類型
           描述
          1 google_test1.mq5
          腳本
          制作屏幕截圖并發(fā)送到多個地址的腳本。
          2
          google_test1.mq5 指標(biāo)
          在每個新燭形上發(fā)送電子郵件的示例指標(biāo)
          3 google.zip 檔案 程序集和測試控制臺應(yīng)用程序項目。

            本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
            轉(zhuǎn)藏 分享 獻(xiàn)花(0

            0條評論

            發(fā)表

            請遵守用戶 評論公約

            類似文章 更多