잊지 않겠습니다.

Unit Test에서 사용되는 NUnit를 보면 [Test] attribute와 [TestFixture] attribute를 이용해서 각각의 Test Class와 Method를 모두 얻어내게 된다.

먼저, Assembly의 Load는 간단하게 Assembly의 static method를 통해서 얻어올 수 있다.

Assembly assem = Assembly.LoadFile(PlugInFileName);

여기에서 Assembly의 각 Class의 Attribute의 조건을 얻어오기 위해서 static class를 하나 생성

public static bool HasAttribute(MemberInfo member, string attrName, bool inherit)
{
    object[] attributes = member.GetCustomAttributes(inherit);
    foreach(Attribute attribute in attributes)
    {
        if(IsInstanceOfType(attrName, attribute))
        {
            System.Diagnostics.Debug.WriteLine(attribute);
            return true;
        }
    }
    return false;
}

얻어진 결과를 linq를 이용해서 검색. (이런 곳에서도 linq는 이용 가능하다. ^^)

var types = from t in assem.GetTypes()
            where Reflect.HasAttribute(t, typeName, true) 
            select t;

이렇게 얻어온 Class를 Activator를 이용해서 Instance를 생성해주면 외부 assembly가 가지고 있는 class의 동적 이용 및 NUnit과 비슷한 동작을 하는 것이 가능해진다. 

ISYNCmailPlugIn plugIn = Activator.CreateInstance(type) as ISYNCmailPlugIn;

Remote에서 사용하게 될 경우에 장점은 다음과 같다. 
1. Compile시에 Dll이 필요하지 않다. 
: 동적 load가 되기 때문에 잦은 변경이 있는 lib인 경우에 사용이 편리하다. 

2. 특정한 Interface나 Attribute를 가지고 있는 경우에 외부에서 사용이 가능하다.
Posted by Y2K
,
Exception을 mail로 보내야지 될 때가 많아서, Exception handler를 간단하게 제작
가장 Key Point는 HttpContext static Member를 이용해서, web에서 발생된 Error도 같이 표현하고 있다는 것이 가장 좋은 점 같다. 

    /// <summary>HtmlError Object.</summary>
    public class ExceptionToHtmlConverter
    {
        public enum ErrorInfoType
        {
            Exception,
            Context
        };
        private delegate string ErrorRendererDelegate(string headerString, NameValueCollection collection);
        static private Hashtable GetErrorInfo(Exception exception)
        {
            Hashtable errorTable = new Hashtable();
            if(exception == null)
            {
                throw new ArgumentNullException("exception");
            }

            // Populate Error Information Collection
            ArrayList errorInfoArray = new ArrayList();
            while(exception != null)
            {

                // Populate Error Information Collection
                NameValueCollection errorInfo = new NameValueCollection();
                errorInfo.Add("Exception Type", exception.GetType().ToString());
                errorInfo.Add("Message", exception.Message);
                errorInfo.Add("Source", exception.Source);
                errorInfo.Add("TargetSite", exception.TargetSite.ToString());
                errorInfo.Add("StackTrace", exception.StackTrace);

                errorInfoArray.Add(errorInfo);
                exception = exception.InnerException;
            }

            errorTable.Add(ErrorInfoType.Exception, errorInfoArray.ToArray());

            if(HttpContext.Current != null)
            {
                Hashtable info = new Hashtable();

                info.Add("QueryString", HttpContext.Current.Request.QueryString);
                info.Add("Form", HttpContext.Current.Request.Form);
                info.Add("Cookies", HttpContext.Current.Request.Cookies);
                info.Add("Session", HttpContext.Current.Session);
                info.Add("Server Variables", HttpContext.Current.Request.ServerVariables);

                errorTable.Add(ErrorInfoType.Context, info);
            }

            return errorTable;

        }
        /// <summary>Returns HTML an formatted error message.</summary>
        static public string GetHtmlError(Exception Ex)
        {
            if(Ex == null)
            {
                throw new ArgumentNullException("Ex");
            }

            // Error Message Header
            StringBuilder sb = new StringBuilder();
            Hashtable errorTable = GetErrorInfo(Ex);
            ErrorRendererDelegate renderer = CollectionToHtmlTable;

            if(HttpContext.Current != null)
            {
                sb.AppendFormat("<font face=\"Arial\" size=\"4\" color=\"red\">An error occurred at {0}<br><font size=\"3\">&nbsp;&nbsp;&nbsp;&nbsp;{1}</font></font><br><br>", HttpContext.Current.Request.Url.ToString(), Ex.Message);
            }

            // Populate Error Information Collection
            foreach(NameValueCollection errorInfo in errorTable[ErrorInfoType.Exception] as object[])
            {
                // Error Information
                sb.Append(renderer("Error Information", BuildCollection(errorInfo)));
            }

            if(errorTable[ErrorInfoType.Context] != null)
            {
                Hashtable info = errorTable[ErrorInfoType.Context] as Hashtable;

                foreach(DictionaryEntry entry in info)
                {
                    sb.AppendFormat("<BR><BR>\n{0}", renderer(entry.Key as string, BuildCollection(entry.Value as ICollection)));
                }
            }

            return sb.ToString();
        }

        /// <summary>Returns HTML an formatted error message.</summary>
        static public string GetTextError(Exception Ex)
        {
            if(Ex == null)
            {
                throw new ArgumentNullException("Ex");
            }

            // Error Message Header
            StringBuilder sb = new StringBuilder();
            Hashtable errorTable = GetErrorInfo(Ex);
            ErrorRendererDelegate renderer = CollectionToTextTable;

            // Populate Error Information Collection
            foreach(NameValueCollection errorInfo in errorTable[ErrorInfoType.Exception] as object[])
            {
                // Error Information
                sb.Append(renderer("Error Information", BuildCollection(errorInfo)));
            }

            if(errorTable[ErrorInfoType.Context] != null)
            {
                Hashtable info = errorTable[ErrorInfoType.Context] as Hashtable;

                foreach(DictionaryEntry entry in info)
                {
                    sb.AppendFormat("\r\n{0}", renderer(entry.Key as string, BuildCollection(entry.Value as ICollection)));
                }
            }

            return sb.ToString();
        }

        #region Private Methods
        static private string CollectionToHtmlTable(string headerString, NameValueCollection collection)
        {

            // Heading Template
            const string heading = @"
  <tr>
    <td bgcolor=""#666666"" colspan=""2"">
      <font face=""Arial"" color=""white""><b>&nbsp;{0}</b></font>
    </td>
  </tr>
";
            // <TD>...</TD> Template
            const string TD = "<td><font face=\"Arial\" size=\"2\"><!--VALUE--></font></td>";

            StringBuilder sb = new StringBuilder();
            // Table Header
            sb.Append("\n<table width=\"100%\" bgcolor=\"#d1d9e4\" cellspacing=\"1\" cellpadding=\"3\">\n");
            sb.AppendFormat(heading, headerString);

            sb.AppendFormat("  <tr bgcolor=\"#d0d0d0\">\n");
            sb.AppendFormat("    {0}\n", TD.Replace("<!--VALUE-->", "&nbsp;<b>Name</b>"));
            sb.AppendFormat("    {0}\n", TD.Replace("<!--VALUE-->", "&nbsp;<b>Value</b>"));
            sb.Append("  </tr>\n");

            // No Body? -> N/A
            if(collection.Count == 0)
            {
                collection = new NameValueCollection();
                collection.Add("N/A", "");
            }

            // Table Body
            for(int i = 0; i < collection.Count; i++)
            {
                sb.AppendFormat("  <tr valign=\"top\" bgcolor=\"{0}\">\n", (i % 2 == 0) ? "white" : "#f4f4f4");
                sb.AppendFormat("    {0}\n", TD.Replace("<!--VALUE-->", collection.Keys[i]));
                sb.AppendFormat("    {0}\n", TD.Replace("<!--VALUE-->", CleanHtml(collection[i])));
                sb.Append("  </tr>\n");
            }

            // Table Footer
            sb.Append("</table>");

            return sb.ToString();
        }
        static private string CollectionToTextTable(string headerString, NameValueCollection collection)
        {

            // Heading Template
            const string heading = "{0}\r\n\r\n";


            StringBuilder sb = new StringBuilder();
            sb.AppendFormat(heading, headerString);


            // No Body? -> N/A
            if(collection.Count == 0)
            {
                collection = new NameValueCollection();
                collection.Add("N/A", "");
            }

            // Table Body
            for(int i = 0; i < collection.Count; i++)
            {
                sb.AppendFormat(" {0} : {1}\r\n", collection.Keys[i], collection[i]);
            }

            return sb.ToString();
        }
        
        static private NameValueCollection BuildCollection(ICollection collection)
        {
            // Overload for HttpCookieCollection collection.
            // Converts HttpCookieCollection to NameValueCollection
            if(collection == null)
            {
                collection = new NameValueCollection();
            }
            NameValueCollection nvCollection = new NameValueCollection();
            IEnumerator en = collection.GetEnumerator();

            object entry;
            while(en.MoveNext())
            {
                entry = en.Current;

                if(collection is HttpCookieCollection)
                {
                    nvCollection.Add(entry.ToString(), (collection as HttpCookieCollection)[entry.ToString()].Value);
                }
                    // Min
                    // CANNOT_MAKE_TEST_CONDITION
                else if(collection is HttpSessionState)
                {
                    nvCollection.Add(entry.ToString(), (collection as HttpSessionState)[entry.ToString()].ToString());
                }
                    // END-CANNOT_MAKE_TEST_CONDITION
                else if(collection is NameValueCollection)
                {
                    if(entry != null)
                    {
                        nvCollection.Add(entry.ToString(), (collection as NameValueCollection)[entry.ToString()].ToString());
                    }
                }
                else
                {
                    throw new NotSupportedException(collection.GetType().ToString());
                }
            }
            return nvCollection;
        }


        static private string CleanHtml(string html)
        {
            // Cleans the string for HTML friendly display
            return (html.Length == 0) ? "" : html.Replace("<", "&lt;").Replace("\r\n", "<BR>").Replace("&", "&amp;").Replace(" ", "&nbsp;");
        }
        #endregion
    }

Posted by Y2K
,
DBCC DBREINDEX('Table이름');

을 이용해서 Index를 Rebuild 시키면 된다. 

DB를 Off-line 또는 사용하지 않는 상태에서 하는 것이 원활하며, 많은 시간을 잡아먹게 된다. (DB의 Index의 조각화가 심할 경우에..)
Posted by Y2K
,