'2018/06'에 해당되는 글 2건

  1. 2018.06.28 C# - HttpWebRequest 네이버 로그인(보안) 2
  2. 2018.06.26 C# - Delegate & Event
Code Programming/C#2018. 6. 28. 10:13

C#을 이용해서 웹페이지로 로그인이 아닌 HttpWebRequest 객체를 이용해서 로그인을 해보았다.

 

인터넷을 검색해보니 유료로 소스를 판매하는 글도 있었고, 로그인 정보를 암호화 하지 않고 전송하는 방법이 많이 있었다.

사실 자바스크립트만 잘 파악하고 C#으로 구현하면 될 문제로 보여 단순한 작업이기도 하고 해서 직접 구현해 보았다.

 

------------------------------------------------------------------------------------------------------------------------------------

우선 네이버 로그인화면의 소스를 보고 구현 순서를 정리했다.

1. 세션정보 가져오기.

2. 암호화할 문자 생성하기.

3. 문자 암호화

4. 로그인 시도

5. 로그아웃 처리

 

참... 없다.

 

순서대로 구현을 해보자.

------------------------------------------------------------------------------------------------------------------------------------

우선 위의 순서에 맞게 메소드를 생성하였다.

 

using System;
using System.Data;
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography;
using System.Text;


        private void LoginNaver()
        {
            CookieContainer cookie = new CookieContainer();
           
            // 1. 세션정보 가져오기
            string strSessionInfo = GetNaverSessionInfo(cookie);

 

            if (String.IsNullOrWhiteSpace(strSessionInfo))
                return;

 

            // 세션정보에는 암호화에 필요한 값들이 콤마(,)로 구분되어 있다.

            string[] arrSessionInfo = strSessionInfo.Split(',');

            string strSessionKey = arrSessionInfo[0];
            string strSessionName = arrSessionInfo[1];
            string strPublicModulusKey = arrSessionInfo[2];
            string strPublicExponentKey = arrSessionInfo[3];
           
            // 2. 암호화할 문자 생성하기
            string strParam = ConvertPassword(strSessionKey, "ID", "Password");

 

            // 3. 문자 암호화
            string strEncParam = EncryptRSA(strPublicModulusKey, strPublicExponentKey, strParam);

 

            // 4. 로그인 시도
            if (TryNaverLogin(cookie, strSessionName, strEncParam))
            {

                // 5. 로그아웃 처리
                TryNaverLogout(cookie);

                MessageBox.Show("Success");
            }
            else
            {
                MessageBox.Show("Fail");
            }
        }

 

------------------------------------------------------------------------------------------------------------------------------------

* 세션정보 가져오기


        private string GetNaverSessionInfo(CookieContainer cookie)
        {
            string strSessionInfo = String.Empty;

 

            HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create("https://nid.naver.com/login/ext/keys.nhn");
            req.Method = WebRequestMethods.Http.Get;
            req.Accept = "*/*";
            req.Host = "nid.naver.com";
            req.UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko";
            req.Referer = "https://nid.naver.com/nidlogin.login";
            req.CookieContainer = cookie;

 

            using (HttpWebResponse res = (HttpWebResponse)req.GetResponse())
            {
                StreamReader sr = new StreamReader(res.GetResponseStream(), Encoding.UTF8);
                string strResult = sr.ReadToEnd();

 

                try
                {
                    strSessionInfo = strResult;
                }
                finally
                {
                    if (sr != null)
                        sr.Close();
                }
            }

 

            return strSessionInfo;
        }

------------------------------------------------------------------------------------------------------------------------------------

* 암호화할 문자 생성하기


        private string ConvertPassword(string strSessionKey, string strId, string strPassword)
        {
            string strResult = String.Empty;

 

            strResult += Convert.ToChar(strSessionKey.Length).ToString();
            strResult += strSessionKey;
            strResult += Convert.ToChar(strId.Length).ToString();
            strResult += strId;
            strResult += Convert.ToChar(strPassword.Length).ToString();
            strResult += strPassword;

 

            return strResult;
        }

------------------------------------------------------------------------------------------------------------------------------------

* 문자 암호화


        private string EncryptRSA(string strPublicModulusKey, string strPublicExponentKey, string strTarget)
        {
            string strResult = String.Empty;

 

            // 공개키 생성
            RSAParameters publicKey = new RSAParameters()
            {
                Modulus = Enumerable.Range(0, strPublicModulusKey.Length)
                .Where(x => x % 2 == 0)
                .Select(x => Convert.ToByte(strPublicModulusKey.Substring(x, 2), 16))
                .ToArray()
                ,
                Exponent = Enumerable.Range(0, strPublicExponentKey.Length)
                .Where(x => x % 2 == 0)
                .Select(x => Convert.ToByte(strPublicExponentKey.Substring(x, 2), 16))
                .ToArray()
            };

 

            try
            {
                RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
                rsa.ImportParameters(publicKey);

    

    // 암호화 및 Byte => String 변환

                byte[] enc = rsa.Encrypt(Encoding.UTF8.GetBytes(strTarget), false);
                strResult = BitConverter.ToString(enc).Replace("-", "").ToLower();
            }
            catch (CryptographicException ex)
            {
                strResult = String.Empty;
            }

 

            return strResult;
        }

------------------------------------------------------------------------------------------------------------------------------------

* 로그인 시도

 

로그인 할 때는 단계가 세부적으로 나뉜다.

우선 암호화한 전송값으로 전송한 뒤에는 SSO 인증을 하는 페이지 주소가 응답이 오고,

이 주소로 접속해야 정상적으로 로그인이 처리가 된다.


        private bool TryNaverLogin(CookieContainer cookie, string strEncName, string strEncValue)
        {
            string strNextURL = String.Empty;
           

            // 특정 파라미터가 데이터 객체인듯 한데 여러개의 아이디를 사용해도 딱히 변동사항이 없었다. 그래서 그대로 사용하기로 했다.
            string strParamFormat = @"bvsd=%7B%22uuid%22%3A%22ae68e175-2232-4dae-8058-83ec84fb1cb3%22%2C%22encData%22%3A%22N4IgrmCWAmIFwgIYFMBsAOZBGA7AVgFoAmIgZiIIBZoUD0AGPdO05AY3UoDMAjLNnqRAAaEADdkAJwDOkAPYA7eCHoA6PKqwiQkaQBU5YNgAsAIsjGQ2yeF0QAbaclEBrZAE8AygBdJct9LwANqgMMphopAKAA5g3gCSCt5SYg4AMnIA5oFwIUjw9KJsyi7asHD0AL7CoIjwWKikRSUAtmX11bX1WFjNCC4tAO7tcESd%2BXAAnOh9IAODciOk43VwPU0gxf1Dcoui5ZQr9Xh4s%2FO79CN4lQC6rh4%2Bfm4Z2cFdFaI8yrCzkJf7ynwICOcHQvRAXwQYG0Wx0%2FxA5RAQJBDQ2kIRMPCWgBCBwOGBNQmnE%2Bymhv2xGNx%2BJRPRJCB%2Bm3CRBGIHQ1MJq0mlDp4ExCEgzJxrPZ70mkx5DNhkCEQpwkwJ70oqB5ZMZ%2FJllKR8ppaO%2BfJ0lBZcoVE1QRBV%2Bsghtl2o5x1OEL1vzwLMo6BNqzNFudrvdKPo4PRkuUegAggAhFnau46BSQbyQBwANQcYBsCBhcha0XsyGSKfsadaCzk8PTdkcyHGYQQ0WGkRicUSyUkqXsLxyeVWhTVIBGVTtoPFvZGWBBYtmIzGg56PdhS393JHOMOM69y8p1xnWHNG%2FKqBBJCX85xOBBpHQDpPlPQh5wyr38Em%2FvB1%2FKWAH7ywF8nOJ6IPQB833qacv1QY9lFHZZByIN1f0pLBDhjNwvF8fxkA7N4Jh7IN9U8AAJeIADE9BZD14CPCVLXhRFyLgSgcNJPDCJIsiUVg71ez%2BNiZyIB9cPJHiv3oRj6UtQVNTo3d0VVKUKVo8dRN5X4JIU7clODdUhImD8lwErjrUkw9OKlDU1PeMETPCQzzJ01BAydLiXSFOjLMdKFLWcozt2kxypVQbTVg%2FByPN%2BAKXMPIgHX0qV8Qi3jfNCri4u8r9Jl1MTZgI4jSPitKNMtd08p00hoqY34itSkqZnc5Te2y1jitWIh7yo355Sa%2BoRKs%2FkOqqoL6ESjFyRoyCAJqmTLQ%2FQL6h%2FWrNJ0HoZtBIbZKxeSxsHQC2q4ndlrwYdJvJVTNrAvS%2FKxMzTp0%2BgJvK3arozQ9KEOi7%2BUQ5aPwyuq5JssaYyieNE3sAsiwzIosxzPNkFB9M%2B1EdNfDTW5RDkSRIGQJJEATRQclALhIBkbwAHl0cx7xsfkJQ4FFCd3LFYctgZ6oQHsRBpBJsmsZx6nadeqY6aZsVKhZlo5B5vGQAJomAFlxap%2BBajYaxc0kSnFEViYGbpbW1WZ0REGV5BVfVhREjYQtoCiTIAHE1csbx3E1zk6chXWhefFm2Y5uWeedo2Tb9mmtddp9BbD58DYDqRTfNy3rbtxAHad4OXf592I5F0XDCcYIQDwUgAB96EL9BC9wQuCApPBKGL0vy6LqhtBOOucHLvBK%2Br1A67LrAO%2BIZu25L3v%2B41Jge%2FLohO%2BbyYJ53SuJNQEuS7bnoF%2B0eyJ9nquN6nkvZ4%2FafREaCfu534%2Fa%2BHwu24IDVUA7q%2F%2B4pVBu8fo%2BQFQIf69rgfj7Lq%2BsDFw3rPK%2BP8JI4GXu3QuU9z5IkASXBo5d344D3oXPA3d4HaBwEXABQDRA4EvtfJB8J8B10QZg%2FBr9J6AMAbAvEddYLEKwf%2FIhtCKRyjId3GBFIGBII%2FFQ%2BEYJoGl3gXg1kqDP5l24dodAOCiGNwkpwOus8b48IfvXHBMiqGzwfjIr%2B3dX4yJYbPEBMiQFEKHtoSYkCy6mNEJMURZcz7hRAJMVBboaFiPSnXUgCCvGEN7l49RfdhHwkmFQwJYSv6zz3lYlhZdNH2PMQksRH4bGF0MaIYKE9%2F7aA%2FKg2xqT6ByLLrkrJ9AAn13hB%2BdRGCS6wP4XPGBEkPzRPLj%2FCkH54nlxvhqD8yTy7b0MrOOeqi8lrxXtAn%2Bwz577x6evLJ35W7lzLr%2FEAPRCEH1WTM9Rvc2HjKoavGBMyv57IWesrAxiiG33GQMxunSiDpI6XkogjjC4KJeQUphWSyAT2kT8whiD%2FnrKiss%2FZPyIlIIaS1ZRoSXndIoSCgZ4L1m%2BLnqk0gbzEXflQeQjFJT3kYsqcC786i26XzyaQSF9zKVtN0Vki8p937fgGWfTpDEJ4UqyZQURISPnctQZi15ndvxssoC0ygBKCBtz6ZQSpVBoF5MoLszuJcvKIUhdK95SrTmqsLsMt0E8q4lwNQMugaC8l4HSQQDBlrRHbw7n0vAEiF7l0tXI7eU9Ok1z4fQARlqO5T1eXI6p6CGHQIqQvYZeAv4yv5es8eV9SCJITQMogqzOlL1hcKgg6rN6TMecys02b6l9JPpMxClcy2bMLp6vJ9864d16fWyFbL61tJJRgWF8aGjmMNdiiBdcMGpJwKIxhKLcCoNXsy7BsLaEtIIWCmd6jzENPvOitZuBdX1M6TgbpO68kcJLlQzdvC5n1JaUIq%2BF68noFQauy9BLaHDKUdeqtt6yVQpfZC2hfS2Qbsvfu5l6ABkHqydYsh6iGkOKQXxOu1S3HCJ3IQhDciNVQpaVyP5zLJjqJekQWeKasDhOzTh2NhKEMsJlaksUE8m3aEeZA2eGCKSPNEW3VerHBpkIrRqR5ciDHly4zWupDHGDLNrilR5rbr5iY7fqsTVHhF8foOYtuU8%2BOH3PYq0Qry3kl0018kuElg08Z8Qxytx6yEWZVcZizVCqGsYrgZwFFmgMmeI0ar1DHC1XyrjpkAJA3n%2Ba8iQL5xBS4%2BYJWqnzNaIuhdBVZk1PntHWd0zCt9rH03LIQT58xya0uBbRcZou3ndOYvRSZ8gc6xFkCfQFsglSaEMdKth1jVKJ6lZa7qoufHGVv0MmQNNbrdMctAQ1nlsLa58fFcsrro2CVlcC3KhheL4SwRXd85bkLgWwS%2FiEsDy2gOwNgqB9%2BUVIGMMO1FTxuH%2FW6edcIrNy8QAxh4H4QYThJBEWtlIaI6Mkj4XZsYZQPAIGf3FYNO70BsHQGQHgRARAuCIRwDwdN9lVN9Xe3IT7UgfsKEyH9gH3hQzeF8J2UAKFSRfYAPqIEJ0kbQbYwYgDlgAL0gPYNmAB6DQ9AAAEAAKAA6lEaAOPpD84AHJ6H5x%2BVQ9AADc%2FPhfE2F%2BBZXeh0Zw6SNznACvleqClwAUT0JQBXABhQ3JuzcK%2BN9b03%2FOLdpAAEr86IAr9Q9AUE4Ad7L53bvSCe98SgyYfuneu%2F50HjQIeCPK9bGsLACuACU%2FP7CQDcPzm27AXCLHGFThAbMCdgHpzYUQzO4a54IAAaRdyaAvmw5D2DRjTuH0RvAg%2FL6mdMsF88eG%2BBYKwyAactGQGLSQTsu%2BFnTFXPvKcQDREgAAD2NjTtWOMmfd46ISBvxhECSGgIMffw%2B2CKDYGASQkhMZsEn%2BILfUIFAuAUDjpQc%2FlBX%2BkE3uICsp9gyCA0bqaxegG4N%2FBAJORATnRAHgXMNfZAT%2FQsP2X%2FdMf%2FJeQoQCYA0AkABMUfNnRQYfOQLgLgJwbwTfafeAXNBiTApwaQWQRQGnDmNGUvUgsGMcHffvQvOQNgBweg7wRgwnZg9MVgyndg2MOHFfaAVvL4JA7fYQ%2BfNgWIGnC2dmQIaQhAJfQCevEQhQJOSATIbGFvHMbGLgNGNoVQkAUXBQcgTQ%2BfcXGnZ%2FbwGnXwQ2UoMwsAR%2FZ%2FQYV%2FNg%2BfDGGnHMMATIKIFQu%2FMg3IBQMALnYQcIyI6I%2BwKIiIuI1nQ2PwUfK2RAIib2YwAABUQGiCkFUBlmSKzGQDSIyOBxyLyMkG0BlmkCXxaHsA91MGJhllME4LAFH0Z1EBqLqIaNUAAA0ZY0h8I9A9AsiRBYj4iYiEjJi4iJiJiQBPA2B0Z29rZVBTArAeZ99J95jPBjBjZ7BVAABVeIfCY2So7QXYzglwI%2FCQMo6QYwVQS4tga4pOZAO4zveYvQUwC3C3bwA4r4n4v47QYXGWLItmdwfI4mC3Po8Y6YnY4wK4m45Afnd4uAOAJ4l4iQFEzI93SYBXfnSQegNE3InMKwU2bnJfAge4xE14ggLgTIgAP2kEGC4GEBJPTy4J5m5y4DiAvzgMMPuKZJzFe0wK4IUFSGCIr2UEwB6DwDYCYFID4BoFIBoAcRwDYFQEmENjYADAIWgGgC%2BEwMGGQB4EyHsAEO%2BBEhoFQGVjYGR34DRzBG4B91IC1JwEQC4GmCIBsCNJNLNJpwkAUHFyqLMJlisD8E%2Fy4G8AZObGNkFxd1T3wlMCzzVmiGMCsEl18REmsOUEQANOb2eItLgArCcEwL32kBp3TxKMrMQGL1L0lPvxLKrG8OUHLMrIxgkI%2Fy%2F0QJCLBibLLPZnbOrLkAbNCP7JbIQDbKrIkOx1xxDN7PLAcFLInKwMMBMHoLAGiGiDRhINUKCEKCbOECbJAJXIACsKzjCkhRy%2F8QBQx0YHBtA7zgZ%2Bdww2ZCzRAnyHBpd98PttBwxdgXB%2BdQwkhIAABHEvP8gCloWs%2FnYmewaAfnHwdwXMbQC3BwSAd7SAVCxAFoTCuoUQNC3C%2B8%2FnQojvVC8mC%2FW%2FC3CiifLPcWdM4oAirMKwRC2syXGWTwVC3GJvdmLii%2FDGeci3QwMmSQaXZAesEAG2ffHCxQBkbPNGQI%2FCkAU4%2BwCQBMLg7QeIbMQ2XckANIIwGARAJ3bilC0QfStgQy1ihQSXQ4uMU%2FOHao8Mkcgg7wKyyXTwKQSALgaoxQcWdwPI4ymQSAVIaozwOijvKwUK2CuIZvfwKKrIm2eiyKrosKl3ZALgKQa%2FZEzwNixCzy7ylKtyvK9GAq1nMKjykq7QHItmBMZ%2FfnNIKIPyvIi45ATIOQZErI4nFqtq7KpYyAdvbq9q%2FnY4wa5E44%2Bq3Q4wXSjynq4a%2BIPKloDCpvBkGaoa8azwdwXCpvbQPQRABE6CnayAUfYIvQI6uAsSwYfnF3LMWsnaq%2FHgIwPY1yji7QJMKQGgbQ4E62K2AnYIiwzIH67Id3L6gnQGzMkUkAoAA%3D%3D%22%7D&enctp=1&encpw={0}&encnm={1}&svctype=0&svc=&viewtype=0&locale=ko_KR&postDataKey=&smart_LEVEL=1&logintp=&url=https%3A%2F%2Fwww.naver.com%2F&localechange=&ls=&xid=&pre_id=&resp=&ru=&id=&pw=";


            string strParam = String.Format(strParamFormat, strEncValue, strEncName);

 

            HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create("https://nid.naver.com/nidlogin.login");
            req.Method = WebRequestMethods.Http.Post;
            req.Accept = "text/html, application/xhtml+xml, image/jxr, */*";
            req.Host = "nid.naver.com";
            req.UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko";
            req.Referer = "https://nid.naver.com/nidlogin.login";
            req.CookieContainer = cookie;
            req.ContentType = "application/x-www-form-urlencoded";
            req.ContentLength = strParam.Length;

 

            StreamWriter sw = new StreamWriter(req.GetRequestStream());
            sw.Write(strParam);
            sw.Close();

            
            using (HttpWebResponse res = (HttpWebResponse)req.GetResponse())
            {
                StreamReader sr = new StreamReader(res.GetResponseStream(), Encoding.UTF8);
                string strResult = sr.ReadToEnd();

                try
                {
                    string strStartIndexString = @"location.replace(""";
                    string strEndIndexString = @""");";

 

                    if (strResult.IndexOf(strStartIndexString) < 0)
                        return false;

 

                    // SSO 인증 페이지 주소 가져오기

                    strNextURL = strResult.Substring(strResult.IndexOf(strStartIndexString) + strStartIndexString.Length);
                    strNextURL = strNextURL.Substring(0, strNextURL.IndexOf(strEndIndexString));
                }
                finally
                {
                    if (sr != null)
                        sr.Close();
                }
            }

 

            // SSO 인증 페이지로 접속

            HttpWebRequest reqSSO = (HttpWebRequest)WebRequest.Create(strNextURL);
            reqSSO.Method = WebRequestMethods.Http.Get;
            reqSSO.Accept = "text/html, application/xhtml+xml, image/jxr, */*";
            reqSSO.Host = "nid.naver.com";
            reqSSO.UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko";
            reqSSO.Referer = "https://nid.naver.com/nidlogin.login";
            reqSSO.CookieContainer = cookie;
           
            using (HttpWebResponse resSSO = (HttpWebResponse)reqSSO.GetResponse())
            {
                StreamReader sr = new StreamReader(resSSO.GetResponseStream(), Encoding.UTF8);
                string strResult = sr.ReadToEnd();

 

                try
                {
                    string strStartIndexString = @"<html><script language=javascript>window.location.replace(""";

 

                    if (strResult.IndexOf(strStartIndexString) < 0)
                        return false;                   
                }
                finally
                {
                    if (sr != null)
                        sr.Close();
                }
            }

 

            // 이부분은 최종적으로 네이버홈으로 다시 접속하는 부분이다.

            HttpWebRequest reqMain = (HttpWebRequest)WebRequest.Create("https://www.naver.com/");
            reqMain.Method = WebRequestMethods.Http.Get;
            reqMain.Accept = "text/html, application/xhtml+xml, image/jxr, */*";
            reqMain.Host = "www.naver.com";
            reqMain.UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko";
            reqMain.Referer = strNextURL;
            reqMain.CookieContainer = cookie;

 

            using (HttpWebResponse resMain = (HttpWebResponse)reqMain.GetResponse())
            {
                StreamReader sr = new StreamReader(resMain.GetResponseStream(), Encoding.UTF8);
                string strResult = sr.ReadToEnd();

 

                try
                {
                    // 필요한거 작성
                }
                finally
                {
                    if (sr != null)
                        sr.Close();
                }
            }

            return true;
        }

------------------------------------------------------------------------------------------------------------------------------------

* 로그아웃 처리


        private bool TryNaverLogout(CookieContainer cookie)
        {
            HttpWebRequest req = (HttpWebRequest)WebRequest.Create("https://nid.naver.com/nidlogin.logout?returl=https://www.naver.com/");
            req.Method = WebRequestMethods.Http.Get;
            req.Accept = "text/html, application/xhtml+xml, image/jxr, */*";
            req.Host = "nid.naver.com";
            req.UserAgent = "Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko";
            req.Referer = "https://my.naver.com/new?svgless=true";
            req.CookieContainer = cookie;

 

            using (HttpWebResponse res = (HttpWebResponse)req.GetResponse())
            {
                StreamReader sr = new StreamReader(res.GetResponseStream(), Encoding.UTF8);
                string strResult = sr.ReadToEnd();

 

                try
                {
                }
                finally
                {
                    if (sr != null)
                        sr.Close();
                }
            }

            return true;
        }

------------------------------------------------------------------------------------------------------------------------------------

 

직접 구현을 해보니 Javascript로 구현된 RSA알고리즘을 C#으로 구현하기 위해 공개키값을 적용하는 부분만 잘 살펴보면

누구든지 쉽게 구현이 가능하다고 생각한다.

 

게다가 웹개발자도 아니라서 웹개발자라면 더욱 쉽게 구현이 가능할 것 같다.

'Code Programming > C#' 카테고리의 다른 글

C# - Delegate & Event  (0) 2018.06.26
Posted by 개돼지오크
Code Programming/C#2018. 6. 26. 17:02

FormParent (부모폼)에서 FormChild (자식폼)을 호출할 때,

FormChild (자식폼)에서 FormParent (부모폼)을 호출할 때,

 

MDI폼을 활용하여 프로퍼티를 활용한다면 간단하게 끝날 사항인거 같다.

하지만 Delegate와 Event를 직접 만들어서 사용하는 예제를 만들기 위해 서로 연관성이 없는 폼으로 연결을 해보았다.

 

 

* 아래는 이벤트를 만들때 사용하기 위한 EventArgs 객체와 Delegate 를 미리 선언한 클래스 파일이다.

------------------------------------------------------------------------------------------------------------------------------------

*** CustomEventClass.cs


    /// <summary>
    /// 이벤트 파라미터 정의 클래스
    /// </summary>
    internal static class EventArgClass
    {
        /// <summary>
        /// 부모폼 호출시 이벤트 파라미터
        /// </summary>
        internal class CallParentEventArgs : EventArgs
        {
            /// <summary>
            /// 자식폼의 메시지
            /// </summary>
            internal string ChildFormMessage { get; set; }
        }

        /// <summary>
        /// 자식폼 호출시 이벤트 파라미터
        /// </summary>
        internal class CallChildEventArgs : EventArgs
        {
            /// <summary>
            /// 부모폼의 메시지
            /// </summary>
            internal string ParentFormMessage { get; set; }
        }
    }

    /// <summary>
    /// 대리자 정의 클래스
    /// </summary>
    internal static class DelegateClass
    {
        /// <summary>
        /// 부모폼 호출 대리자
        /// </summary>
        /// <param name="childForm">자식폼</param>
        /// <param name="args">자식폼 이벤트 파라미터</param>
        internal delegate void CallParent(System.Windows.Forms.Form childForm, EventArgClass.CallParentEventArgs args);

        /// <summary>
        /// 자식폼 호출 대리자
        /// </summary>
        /// <param name="parentForm">부모폼</param>
        /// <param name="args">부모폼 이번테 파라미터</param>
        internal delegate void CallChild(System.Windows.Forms.Form parentForm, EventArgClass.CallChildEventArgs args);
    }

------------------------------------------------------------------------------------------------------------------------------------

 

사실 아직도 대리자에 대한 정확한 개념이 머리속에 잡히지 않았지만 난 주로 Event 를 만들때 사용할 것 같다.

 

EventArgs 클래스 같은 경우에는 커스텀으로 만들 경우에 반드시 EventArgs 형식으로 만들 필요는 없다.

원하는 구조체나 클래스를 만들어 사용하여도 무관하다.

 

대리자의 파라미터 구성요소로는 보통 이벤트에 포함되는 파라미터가 Sendor, EventArgs 인 형태가 대부분이여서 비슷하게 만들어 보았다.

파라미터의 요소는 생략 또는 2개 이상의 형식을 넣어도 무관하다.

 

또한 리턴값을 void 이외의 값으로 지정하면 이벤트이지만 값을 리턴받아 후위처리가 가능한 이벤트로 생성할 수 있는 것 같다.

 

 

 

* 아래는 폼 코딩이다.

------------------------------------------------------------------------------------------------------------------------------------

*** FormChild.cs

 

   public partial class FormChild : Form
    {
        /// <summary>
        /// 부모폼 호출 이벤트
        /// </summary>
        internal event DelegateClass.CallParent CallParentEvent;

        private string m_strFormName = String.Empty;


        public FormChild(FormParent frm)
        {
            InitializeComponent();

            this.m_strFormName = Guid.NewGuid().ToString().ToUpper().Replace("-", "");

            this.btnCallParent.Click += (s, e) => { CallParent(); };
            this.FormClosed += (s, e) => { frm.CallChildEvent -= ResponseParent; };
            frm.CallChildEvent += ResponseParent;
        }


        private void CallParent()
        {
            if (this.CallParentEvent != null)
            {
                CallParentEvent(this, new EventArgClass.CallParentEventArgs() { ChildFormMessage = String.Format("Hi. I'm {0}.", this.m_strFormName) });
            }
        }

        private void ResponseParent(Form parentForm, EventArgClass.CallChildEventArgs args)
        {
            if (this.CallParentEvent != null)
            {
                CallParentEvent(this, new EventArgClass.CallParentEventArgs() { ChildFormMessage = String.Format("Why? {0}.", this.m_strFormName) });
            }
        }
    }

------------------------------------------------------------------------------------------------------------------------------------

*** FormParent.cs


    public partial class FormParent : Form
    {
        /// <summary>
        /// 자식폼 호출 이벤트
        /// </summary>
        internal event DelegateClass.CallChild CallChildEvent;
      

        public FormParent()
        {
            InitializeComponent();
           
            this.btnNewChild.Click += (s, e) => { CreateChildForm(); };
            this.btnCallChild.Click += (s, e) => { CallChildForm(); };
        }

       
        private void CreateChildForm()
        {
            FormChild form = new FormChild(this);
            form.CallParentEvent += (s, e) => { CallParent(e); };

            form.Show();
        }

        private void CallChildForm()
        {
            if (this.CallChildEvent != null)
            {
                CallChildEvent(this, new EventArgClass.CallChildEventArgs() { ParentFormMessage = "HEY" });
            }
        }


        private void CallParent(EventArgClass.CallParentEventArgs e)
        {
            this.txtEventMessage.AppendText(e.ChildFormMessage);
            this.txtEventMessage.AppendText(Environment.NewLine);
        }

    }

------------------------------------------------------------------------------------------------------------------------------------

 

간단하게 부모폼에서 자식폼을 Show해주고 자식폼에서 버튼 클릭시 부모폼의 TextBox에 어떤 자식폼에서 부모폼을 호출하였는지 출력하고,

부모폼에서 자식폼 모두를 호출하였을 때, 활성화되어 있는 자식폼이 모두 부모폼의 TextBox에 출력하도록 구성했다.

 

별다른 내용은 없으므로.... 더이상의 설명은 생략 '-'

 

 

 

 

'Code Programming > C#' 카테고리의 다른 글

C# - HttpWebRequest 네이버 로그인(보안)  (2) 2018.06.28
Posted by 개돼지오크