[¸ÞŸµ¥ÀÌÅÍ È°¿ë ¨ê] ¾îÆ®¸®ºäÆ® ¿À¸®¿£Æ¼µå ÇÁ·Î±×·¡¹Ö
·ù´ë¿ø(SK C&C ÇÁ·¹ÀÓ °³¹ß ¹× Áö¿ø ¾÷¹« ´ã´ç) 2007/12/04
[Áöµð³ÝÄÚ¸®¾Æ] ÃÖ±Ù ÀÚ¹Ù ¾î³ëÅ×À̼Ç(Annotation)ÀÇ µîÀåÀ¸·Î ¾îÆ®¸®ºäÆ® ¿À¸®¿£Æ¼µå ÇÁ·Î±×·¡¹Ö(attribute oriented programming)¿¡ ´ëÇÑ °ü½ÉÀÌ ¸¹¾ÆÁö°í ÀÖ´Ù. ÇÏÁö¸¸ ¾îÆ®¸®ºäÆ® ¿À¸®¿£Æ¼µå ÇÁ·Î±×·¡¹ÖÀº ¾î´À ³¯ °©Àڱ⠵îÀåÇÑ °³³äÀÌ ¾Æ´Ï´Ù. ƯÈ÷ ¸¶ÀÌÅ©·Î¼ÒÇÁÆ®(ÀÌÇÏ MS) Áø¿µ¿¡¼´Â COMÀ̳ª COM+ °³¹ß¿¡¼ ºÎºÐÀûÀ¸·Î ÀÌ¹Ì »ç¿ëÇϰí ÀÖ¾úÀ¸¸ç ´å³ÝÀÇ °æ¿ì ¾îÆ®¸®ºäƼµå ÇÁ·Î±×·¡¹ÖÀ̶ó´Â À̸§À¸·Î ÃÊâ±âºÎÅÍ Áö¿øÇϰí ÀÖ´ø °³³äÀÌ´Ù.
¾îÆ®¸®ºäÆ® ¿À¸®¿£Æ¼µå ÇÁ·Î±×·¡¹ÖÀ̶õ ÇÁ·Î±×·¥ ·¹º§¿¡¼ÀÇ ¸¶Å· ±â¹ýÀÌ´Ù. À̸¦ »ç¿ëÇϸé ÇÁ·Î±×·¥À» °³¹ßÇÒ ¶§ ÇÁ·Î±×·¥°ú °ü·ÃµÈ ¸ÞŸµ¥ÀÌÅÍ Á¤º¸¸¦ ÀúÀåÇϰí ÀÌ Á¤º¸¸¦ ÀÌ¿ëÇÏ¿© µðÀÚÀΠŸÀÓÀ̳ª ÄÄÆÄÀÏ Å¸ÀÓ, ·Îµù ¶Ç´Â ·±Å¸ÀÓ ½Ã¿¡ ¿øÇÏ´Â µ¿ÀÛÀ» ¼öÇàÇϵµ·Ï ÇÒ ¼ö ÀÖ´Ù.
¿¹¸¦ µé¸é Æ®·£Àè¼Ç(Transaction)À̶ó´Â ¾îÆ®¸®ºäÆ®¸¦ ¼±¾ðÇÑ Å¬·¡½º´Â Ŭ·¡½ºÀÇ ¸Þ¼Òµå¸¦ ½ÇÇàÇÒ ¶§ Æ®·£Àè¼Ç ÄÁÅØ½ºÆ® ³»¿¡¼ ¼öÇàµÇµµ·Ï ÇÑ´Ù. ÀÌ·¯ÇÑ ±â¹ýÀº ÄÚ¾î ºñÁî´Ï½º ·ÎÁ÷°ú Æ®·£Àè¼Ç, ·Î±ë°ú °°Àº Ⱦ´Ü °ü½É»ç(Cross-cutting concerns)¸¦ ºÐ¸®ÇÑ´Ù´Â Á¡¿¡¼ AOP(Aspect Oriented Programming) ±â¹ý°ú À¯»çÇÏ´Ù°í ÇÒ ¼ö ÀÖ´Ù.
¾îÆ®¸®ºäƼµå ÇÁ·Î±×·¡¹Ö ÆÐ·¯´ÙÀÓÀÇ ½ÃÀÛ
¾îÆ®¸®ºäƼµå ÇÁ·Î±×·¡¹Ö ±â¹ýÀº COM ±â¹Ý ÇÁ·Î±×·¡¹Ö¿¡¼ÀÇ ÀÎÅÍÆäÀ̽º Á¤ÀÇ ¾ð¾î(Interface Definition Language)¿¡¼ »ç¿ëµÇ±â ½ÃÀÛÇß´Ù. ¶óÀ̺귯¸®¿Í Ŭ·¡½ºÀÇ uuid³ª helpstring°°Àº ÇÁ·Î±×·¥¿¡ ´ëÇÑ ¸ÞŸµ¥ÀÌÅÍ °ªµéÀ» ¶óÀ̺귯¸®³ª Ŭ·¡½ºÀÇ Á¤ÀÇ¿¡ ´ÙÀ½°ú °°ÀÌ ¼±¾ðÇØ ÄÄÆÄÀÏ ½Ã¿¡ ÂüÁ¶ÇÒ ¼ö ÀÖµµ·Ï ÇÏ¿´´Ù.
[uuid(74731E6F-A0E8-47FB-833C-8D6C75E85981),
helpstring("MessengerAx Control"), control ]
coclass MessengerAx
ÀÌ·¯ÇÑ ±â¹ýÀº COM+ ±â¹ÝÀ¸·Î ¹ßÀüÇÏ¸é¼ ¾ÖÇø®ÄÉÀ̼ÇÀÇ Æ®·£Àè¼Ç ¼³Á¤°ú Ç®¸µ, º¸¾È ¼³Á¤ µîÀÇ ¸ÞŸµ¥ÀÌÅÍ Á¤º¸¸¦ ±¸¼º¿ä¼Ò ¼ºñ½º¿Í °°Àº º°µµÀÇ ÀúÀå¼Ò¸¦ ÀÌ¿ëÇØ µî·ÏÇÑ ÈÄ¿¡ ÀÌ Á¤º¸¸¦ ·±Å¸ÀÓ ½Ã¿¡ ÂüÁ¶Çؼ ÇÁ·Î±×·¥ÀÌ µ¿ÀÛÇϵµ·Ï ÇÏ¿´´Ù.
<ȸé 1> com+ Æ®·£Àè¼Ç ¼³Á¤ ȸé
´å³Ý¿¡¼ÀÇ ¾îÆ®¸®ºäƼµå ÇÁ·Î±×·¡¹Ö ±â¹ýÀº À̺¸´Ù ÇÑ ´Ü°è ´õ ¹ßÀüµÈ ÇüÅ·Π»ç¿ëÇÒ ¼ö ÀÖ´Ù. ¾îÆ®¸®ºäÆ®¸¦ º°µµÀÇ ¼³Á¤ ÀúÀå¼Ò°¡ ¾Æ´Ñ ÇÁ·Î±×·¥ ³»¿¡ Á÷Á¢ ÀúÀåÇÒ ¼ö Àֱ⠶§¹®ÀÌ´Ù.
¶ÇÇÑ ¹Ì¸® Á¤ÀÇµÈ ºôÆ®ÀÎ(built-in) ¾îÆ®¸®ºäÆ®»Ó¸¸ ¾Æ´Ï¶ó »ç¿ëÀÚ Ä¿½ºÅÒ ¾îÆ®¸®ºäÆ®¸¦ Á¤ÀÇÇÏ¿© »ç¿ëÇÒ ¼ö ÀÖµµ·Ï ÇÏ¿© ¿ÏÀüÇÑ ¾îÆ®¸®ºäÆ® ¿À¸®¿£Æ¼µå ÇÁ·Î±×·¡¹ÖÀ» Áö¿øÇϰí ÀÖ´Ù.
[WebMethod]
public string MyService()
{¡¦}
ºôÆ®ÀÎ(built-in) ¾îÆ®¸®ºäÆ®
´å³Ý¿¡¼´Â ´Ù¾çÇÑ ºôÆ®ÀÎ ¾îÆ®¸®ºäÆ®¸¦ Á¦°øÇÑ´Ù. ÀÌ Áß¿¡¼ ÀÚÁÖ ¾²ÀÌ´Â ºôÆ®ÀÎ ¾îÆ®¸®ºäÆ® ¸î °³¿¡ ´ëÇØ¼¸¸ °£´ÜÈ÷ ¾Ë¾Æº¸ÀÚ. ´Ù¸¥ ¾îÆ®¸®ºäÆ®¿¡ ´ëÇØ¼´Â MSDN µîÀ» Âü°íÇÏ±æ ¹Ù¶õ´Ù.
´å³ÝÀÇ ÁÖ¿ä ºôÆ®ÀÎ ¾îÆ®¸®ºäƼ
¡Ü System.CLSCompliantAttribute : ÇÁ·Î±×·¥ÀÌ CLS(Common Language Specification)À» ÁؼöÇÑ´Ù°í ¼±¾ðÇÏ´Â ¾îÆ®¸®ºäÆ®(CLS´Â ´Ù¾çÇÑ ¾ð¾î·Î ±¸ÇöµÈ ¾î¼Àºí¸®µéÀÌ »óÈ£ ¿î¿ëÇϴµ¥ ¹®Á¦°¡ ¾øµµ·Ï Çϱâ À§ÇØ ÁöÁ¤ÇÑ ½ºÆå).
¡Ü System.EnterpriseServices.TransactionAttribute : Ŭ·¡½ºÀÇ Æ®·£Àè¼ÇÀ» ¼±¾ðÇϱâ À§ÇÑ ¾îÆ®¸®ºäÆ®
¡Ü System.ObsoleteAttribute : ÇØ´ç ¸Þ¼Òµå³ª ÇÁ·ÎÆÛƼ µîÀÌ ´õ ÀÌ»ó »ç¿ëµÇÁö ¾Ê´Â´Ù°í ¼±¾ðÇÏ´Â ¾îÆ®¸®ºäÆ®
¡Ü System.SerializableAttribute : Ŭ·¡½º¸¦ Á÷·ÄÈ ÇÒ ¼ö ÀÖµµ·Ï ¼±¾ðÇÏ´Â ¾îÆ®¸®ºäÆ®
¡Ü System.Web.Services.WebMethodAttribute : À¥¼ºñ½ºÀÇ ¸Þ¼Òµå°¡ À¥¼ºñ½º Ŭ¶óÀÌ¾ðÆ®¿¡ ÀÇÇØ È£ÃâµÉ ¼ö ÀÖµµ·Ï ¼±¾ðÇÏ´Â ¾îÆ®¸®ºäÆ®
¡Ü System.Web.Services.WebServiceAttribute : À¥¼ºñ½ºÀÇ ³×ÀÓ½ºÆäÀ̽º¿Í °°Àº Ãß°¡ Á¤º¸¸¦ Àü´ÞÇϱâ À§ÇÑ ¾îÆ®¸®ºäÆ®
¡Ü System.Web.Services.WebServiceBindingAttribute : À¥¼ºñ½º°¡ Áö¿øÇÏ´Â ¹ÙÀεù Á¤º¸¸¦ ¼±¾ðÇϱâ À§ÇÑ ¾îÆ®¸®ºäÆ®
¡Ü System.Web.Services.Protocols.SoapDocumentMethodAttribute : À¥¼ºñ½º ¹ÙÀεù Á¤º¸¿Í À¥ ¸Þ¼Òµå¸¦ ¸ÅÇÎÇϱâ À§ÇÑ ¾îÆ®¸®ºäÆ®
Ä¿½ºÅÒ ¾îÆ®¸®ºäÆ® »ý¼º
ÀÌÁ¦ ´å³ÝÀÇ Ä¿½ºÅÒ ¾îÆ®¸®ºäÆ®¸¦ »ý¼ºÇÏ´Â ¹æ¹ý¿¡ ´ëÇØ¼ »ìÆìº¸ÀÚ. ´å³ÝÀÇ ¾îÆ®¸®ºäÆ®´Â System.Attribute Ŭ·¡½º¸¦ »ó¼Ó¹ÞÀº Ŭ·¡½º·Î Á¤ÀÇÇÑ´Ù. ¾îÆ®¸®ºäÆ®µµ ÇϳªÀÇ Å¬·¡½ºÀ̱⠶§¹®¿¡ »ý¼ºÀÚ³ª Çʵå, ¸Þ¼Òµå µîÀ» °¡Áú ¼ö ÀÖÀ¸¸ç »ó¼Óµµ °¡´ÉÇÏ´Ù. ¾îÆ®¸®ºäÆ® Ŭ·¡½ºµµ ÀÏ¹Ý Å¬·¡½ºÃ³·³ »ý¼ºÀÚ°¡ ¾ø´Â °æ¿ì µðÆúÆ® »ý¼ºÀÚ¸¦ ÀÚµ¿À¸·Î »ý¼ºÇÑ´Ù.
<¸®½ºÆ® 1>ÀÇ ¾îÆ®¸®ºäÆ® Ŭ·¡½º¸¦ »ìÆìº¸ÀÚ. ÀϹÝÀûÀ¸·Î ¾îÆ®¸®ºäÆ®¸íÀº Attribute¶ó´Â Á¢¹Ì¾î¸¦ °¡Áöµµ·Ï ÇÑ´Ù. ¾îÆ®¸®ºäÆ®ÀÇ Á¤ÀÇ ºÎºÐÀ» º¸¸é ¾îÆ®¸®ºäÆ® Ŭ·¡½º¿¡ ´ëÇÑ ¾îÆ®¸®ºäÆ®·Î System.AttributeUsage¸¦ ¼±¾ðÇÑ °ÍÀ» º¼ ¼ö ÀÖ´Ù.
ÀÌ ¾îÆ®¸®ºäÆ®ÀÇ ¿ëµµ´Â ÇØ´ç ¾îÆ®¸®ºäÆ®¸¦ »ç¿ëÇÒ ¼ö Àִ Ÿ±ê(¿¹¸¦ µé¸é Ŭ·¡½º, ¸Þ¼Òµå, Çʵå, ¾î¼Àºí¸® µî)À» ÁöÁ¤ÇÏ°í ¾îÆ®¸®ºäÆ®ÀÇ Áߺ¹ »ç¿ëÀ» Çã¿ëÇϰųª ¾îÆ®¸®ºäÆ®¿¡ ´ëÇÑ »ó¼Ó Çã¿ë µîÀ» ÁöÁ¤ÇÒ ¶§ »ç¿ëÇÑ´Ù. ¾îÆ®¸®ºäÆ®µµ Ŭ·¡½ºÀ̱⠶§¹®¿¡ Ÿ±êÀÌ Å¬·¡½ºÀÎ ¾îÆ®¸®ºäÆ®µéÀº ¾îÆ®¸®ºäÆ®¿¡ ¼±¾ðÇÒ ¼ö ÀÖ´Ù. AttributeUsageAttribute Ŭ·¡½ºµµ ÀÚ±â ÀÚ½ÅÀ» ¾îÆ®¸®ºäÆ®·Î ¼±¾ðÇÏ¿© Ÿ±êÀ» ÁöÁ¤Çϰí ÀÖ´Ù.
[AttributeUsage(AttributeTargets.Class, Inherited=true)¡¦]
public sealed class AttributeUsageAttribute : Attribute
{¡¦}
<¸®½ºÆ® 1>ÀÇ ¿¹¿¡¼´Â ¾îÆ®¸®ºäÆ®¸¦ Ŭ·¡½º¿Í ¸Þ¼Òµå ·¹º§¿¡¼ »ç¿ëÇÒ ¼ö ÀÖµµ·Ï ÁöÁ¤ÇÏ¿´À¸¸ç Áߺ¹À» Çã¿ëÇϰí ÀÖ´Ù. »ó¼ÓÀ» ÁöÁ¤ÇÏÁö ¾Ê´Â °æ¿ì true °ªÀÌ ¼³Á¤µÈ´Ù.
<¸®½ºÆ® 1>¾îÆ®¸®ºäÆ® Ŭ·¡½º Á¤ÀÇ
[System.AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple=true)]
class MyAttribute : Attribute {
private String firstName;
private String lastName;
public MyAttribute(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
}
class My2Attribute : MyAttribute {
private String middleName;
public String MiddleName {
get { return middleName; }
set { middleName = value; }
}
public My2Attribute() : base("defaultFirstName","defaultLastName") {}
}
¾îÆ®¸®ºäÆ®¿¡¼ »ç¿ëÇÒ ¼ö ÀÖ´Â ÆÄ¶ó¹ÌÅÍÀÇ Á¾·ù´Â ±âº»ÇüÀÎ boolÀ̳ª char, String µî°ú ´õºÒ¾î System.Type°ú enum µîµµ Áö¿øÇÑ´Ù.
<¸®½ºÆ®1>¿¡¼ Á¤ÀÇÇÑ ¾îÆ®¸®ºäÆ®¸¦ »ç¿ëÇÏ´Â ¿¹¸¦ »ìÆìº»´Ù. <¸®½ºÆ® 2>¿Í °°ÀÌ Å¬·¡½º¸¦ Á¤ÀÇÇÑ ÈÄ¿¡ ÇØ´ç Ŭ·¡½º¿Í ¸Þ¼Òµå¿¡ ¡®MyAttribute¡¯ ¾îÆ®¸®ºäÆ®¸¦ ¼±¾ðÇØ º¸ÀÚ. ¾îÆ®¸®ºäÆ® Àüü À̸§(MyAttribute)À» »ç¿ëÇØµµ µÇ°í ¾îÆ®¸®ºäÆ® ¸í¿¡¼ Attribute Á¢¹Ì»ç¸¦ Á¦¿ÜÇÑ À̸§(My)¸¸ »ç¿ëÇØµµ µÈ´Ù.
¾îÆ®¸®ºäÆ® ¼±¾ð ½Ã¿¡´Â ¾îÆ®¸®ºäÆ® »ý¼ºÀÚ¸¦ »ç¿ëÇÏ°Ô µÈ´Ù. µû¶ó¼ MyAttributeÀÇ °æ¿ì MyAttribute(firstName, lastName)¸¦ È£ÃâÇÏ°Ô µÈ´Ù. »ý¼ºÀÚÀÇ ÆÄ¶ó¹ÌÅÍ ÀÌ¿ÜÀÇ ´Ù¸¥ ÇÁ·ÎÆÛƼ´Â MyAttribute2¿Í °°ÀÌ named ±â¹ÝÀÇ ÆÄ¶ó¹ÌÅÍ(MiddleName="K")·Î Àü´ÞÇÑ´Ù.
¼±¾ðÀÇ À§Ä¡´Â ÀϹÝÀûÀ¸·Î ´ëºÎºÐÀÇ ¾îÆ®¸®ºäÆ®´Â Ÿ±ê ŸÀÔÀÇ ¹Ù·Î À§¿¡ ¼±¾ðÇÏ¸ç ¾îÆ®¸®ºäÆ® ½Äº°ÀÚ(Attribute Identifier)¸¦ ÀÌ¿ëÇØ ¾îÆ®¸®ºäÆ®ÀÇ Àû¿ë ´ë»óÀ» ¸íÈ®È÷ ÇÒ ¼ö ÀÖ´Ù.
¿¹¸¦ µé¾î ¸Þ¼ÒµåÀÇ ¸®ÅÏ °ª¿¡ ¾îÆ®¸®ºäÆ®¸¦ Àû¿ëÇÏ°í ½Í´Ù¸é ¸Þ¼Òµå À§¿¡ ¼±¾ðÇÒ ¶§¿¡´Â [return:My2]¿Í °°ÀÌ ¼±¾ðÇÏ¸é µÈ´Ù. ¶ÇÇÑ ¾î¼Àºí¸®¿¡ ´ëÇÑ ¾îÆ®¸®ºäÆ®ÀÇ °æ¿ì AssemblyInfo ÆÄÀÏ¿¡ [assembly: MyAttribute("DaeWon", "Ryu")]¿Í °°ÀÌ ¼±¾ðÇÏ¸é µÈ´Ù.
<¸®½ºÆ® 2>¾îÆ®¸®ºäÆ® »ç¿ë
[MyAttribute("daewon","ryu")]
[My2Attribute(MiddleName="K")]
public class BizService {
public BizService() {¡¦}
[My2]
public void InsertMethod() { ¡¦}
}
<¸®½ºÆ® 2>¿Í °°ÀÌ ¾îÆ®¸®ºäÆ®¸¦ ¼±¾ðÇÑ Å¬·¡½ºÀÇ ¸ÞŸµ¥ÀÌÅÍ Á¤º¸¸¦ »ìÆìº¸ÀÚ. ¿ì¼± ´å³Ý Äֿܼ¡¼ ILDASM ¸í·ÉÀ» ÅëÇØ MS¿¡¼ Á¦°øÇÏ´Â µð½º¾î¼Àºí·¯¸¦ ½ÇÇàÇÑ ÈÄ¿¡ ¾Õ¼ »ý¼ºÇÑ ¾î¼Àºí¸® ÆÄÀÏÀ» ¿¾îº¸¸é <ȸé 2>¿Í °°Àº Ŭ·¡½º ±¸Á¶ Á¤º¸¸¦ È®ÀÎÇÒ ¼ö ÀÖ´Ù.
<ȸé 2> ILDASM ȸé
ILDASM ¾ÖÇø®ÄÉÀ̼ÇÀÇ [View]-[MetaInfo]-[Show!] ¸Þ´º¸¦ ¼±ÅÃÇϸé(¶Ç´Â
+) ÇØ´ç ¾î¼Àºí¸®ÀÇ ¸ÞŸµ¥ÀÌÅÍ Á¤º¸¸¦ Á¶È¸ÇÒ ¼ö Àִ ȸéÀÌ Ç¥½ÃµÈ´Ù.
ÀÌ È¸é ³»¿ëÀ» ÀÚ¼¼È÷ »ìÆìº¸¸é <¸®½ºÆ® 3>°ú °°ÀÌ BizComp.BizService Ŭ·¡½º¿¡ ¼±¾ðµÈ Ä¿½ºÅÒ ¾îÆ®¸®ºäÆ® Á¤º¸¿Í ¸Þ¼Òµå¿¡ ¼±¾ðµÈ Ä¿½ºÅÒ ¾îÆ®¸®ºäÆ® Á¤º¸¸¦ È®ÀÎÇÒ ¼ö ÀÖÀ» °ÍÀÌ´Ù.
TypDefName: BizComp.BizService (02000002)
Flags : [Public] [AutoLayout] [Class] [AnsiClass] [BeforeFieldInit] (00100001)
Extends : 01000001 [TypeRef] System.Object
Method #1 (06000001)
-------------------------------------------------------
MethodName: .ctor (06000001)
Flags : [Public] [HideBySig] [ReuseSlot] [SpecialName] [RTSpecialName] [.ctor] (00001886)
RVA : 0x000020d0
ImplFlags : [IL] [Managed] (00000000)
CallCnvntn: [DEFAULT]
hasThis
ReturnType: Void
No arguments.
Method #2 (06000002)
-------------------------------------------------------
MethodName: InsertMethod (06000002)
Flags : [Public] [HideBySig] [ReuseSlot] (00000086)
RVA : 0x000020db
ImplFlags : [IL] [Managed] (00000000)
CallCnvntn: [DEFAULT]
hasThis
ReturnType: Void
No arguments.
CustomAttribute #1 (0c000010)
-------------------------------------------------------
CustomAttribute Type: 06000006
CustomAttributeName: BizComp.My2Attribute :: instance void .ctor()
Length: 4
Value : 01 00 00 00 > <
ctor args: ()
CustomAttribute #1 (0c000011)
-------------------------------------------------------
CustomAttribute Type: 06000006
CustomAttributeName: BizComp.My2Attribute :: instance void .ctor()
Length: 19
Value : 01 00 01 00 54 0e 0a 4d 69 64 64 6c 65 4e 61 6d > T MiddleNam <
: 65 01 4b >e K <
ctor args: ()
CustomAttribute #2 (0c000012)
-------------------------------------------------------
CustomAttribute Type: 06000003
CustomAttributeName: BizComp.MyAttribute :: instance void .ctor(class System.String,class System.String)
Length: 15
Value : 01 00 06 64 61 65 77 6f 6e 03 72 79 75 00 00 > daewon ryu <
ctor args: ("daewon0yu", "ryu")
Ä¿½ºÅÒ ¾îÆ®¸®ºäÆ®ÀÇ È°¿ë
ÀÌÁ¦ ¸ÞŸµ¥ÀÌÅÍ·Î Æ÷ÇÔµÈ Ä¿½ºÅÒ ¾îÆ®¸®ºäÆ®¸¦ ÇÁ·Î±×·¥¿¡¼ Ȱ¿ëÇÏ´Â ¹æ¹ý¿¡ ´ëÇØ¼ »ìÆìº¼ Â÷·Ê´Ù. ƯÁ¤ ÇʵåÀÇ ±æÀ̸¦ °ËÁõÇÏ´Â ¿¹Á¦¸¦ ±¸ÇöÇØ º¸µµ·Ï ÇϰڴÙ.
¿ì¼± C#À¸·Î console application ÇÁ·ÎÁ§Æ®¸¦ Çϳª »ý¼ºÇÑ´Ù. ÇÁ·ÎÁ§Æ®ÀÇ À̸§Àº ValidationTest·Î ÇÏÀÚ.
¸ÕÀú »ç¿ëÇÏ·Á´Â ¾îÆ®¸®ºäÆ®¸¦ Ãß°¡Çϱâ À§ÇØ [Ãß°¡]-[»õ·Î¿î ¾ÆÀÌÅÛ]¿¡¼ ValidationAttribute Ŭ·¡½º¸¦ Ãß°¡ÇÑ´Ù. System.Attribute Ãß»ó Ŭ·¡½º¸¦ »ó¼Ó¹Þ°í ¾îÆ®¸®ºäÆ®ÀÇ Å¸±êÀº Çʵå·Î ÁöÁ¤ÇÑ´Ù. ¸â¹ö º¯¼ö·Î int ŸÀÔÀÎ minLength, maxLength¿Í String ŸÀÔÀÎ msg(ÀÌ Çʵå´Â À¯È¿¼º °Ë»ç ½ÇÆÐ ½Ã Ãâ·ÂÇÒ ¿¡·¯ ¸Þ½ÃÁö´Ù)¸¦ Ãß°¡ÇÑ´Ù.
±×¸®°í ÀÌ ¸â¹ö °ªµéÀ» ÆÄ¶ó¹ÌÅÍ·Î ÇÏ´Â »ý¼ºÀÚ¸¦ Ãß°¡ÇÑ´Ù. ¸¶Áö¸·¿¡ ÀÎÀÚ·Î ³Ñ¾î¿Â minLength¿Í maxLengthÀÇ ±æÀ̸¦ ºñ±³ÇÏ¿© À¯È¿¼ºÀ» °Ë»çÇÏ´Â IsValid ¸Þ¼Òµå¸¦ Ãß°¡ÇÑ´Ù. ÀÛ¼ºµÈ ³»¿ëÀº <¸®½ºÆ® 4>¿Í °°´Ù.
<¸®½ºÆ® 4> ValidationAttribute Ŭ·¡½º ¼Ò½º
[System.AttributeUsage(AttributeTargets.Field, AllowMultiple=true)]
class ValidationAttribute : Attribute {
//ÇÊµå ¹× »ý¼ºÀÚ »ý·«
public bool IsValid(String data)
{
int lengh = data.Length;
if (lengh >= minLength && lengh < maxLength)
return true;
else return false;
}
}
ÀÌÁ¦ ½ÇÁ¦ À¯È¿¼ºÀ» °Ë»çÇϴ Ŭ·¡½º¸¦ ¸¸µé¾î º¸ÀÚ. [Ãß°¡]-[»õ·Î¿î ¾ÆÀÌÅÛ]¿¡¼ ValidationCheck Ŭ·¡½º¸¦ Ãß°¡ÇÑ´Ù. ÀÌ Å¬·¡½º´Â ÀνºÅϽºÈ ÇÒ Çʿ䰡 ¾øÀ¸¹Ç·Î static Ŭ·¡½º·Î Á¤ÀÇÇÏ¸é µÈ´Ù. static String CheckValidation(Object data) ¸Þ¼Òµå¸¦ Ãß°¡ÇÑ´Ù.
ÀÌ ¸Þ¼Òµå¿¡¼´Â ´å³ÝÀÇ reflection ±â´ÉÀ» ÀÌ¿ëÇØ ÆÄ¶ó¹ÌÅÍ·Î ¹ÞÀº °´Ã¼ÀÇ Å¸ÀÔ Á¤º¸¸¦ »ý¼ºÇÑ ÈÄ ÇØ´ç ŸÀÔÀ¸·ÎºÎÅÍ Çʵå Á¤º¸¸¦ Àоî¿À°í Çʵ忡 Validation ¾îÆ®¸®ºäÆ®°¡ ¼±¾ðÀÌ µÇ¾î ÀÖ´ÂÁö È®ÀÎÇÑ´Ù. ±× °á°ú Validation ¾îÆ®¸®ºäÆ®°¡ ÇʵåÀÇ °ªÀÌ À¯È¿ÇÑÁö¸¦ °Ë»çÇÑ´Ù. ÀÛ¼ºÇÑ °á°ú´Â <¸®½ºÆ® 5>¿Í °°´Ù.
<¸®½ºÆ® 5> ValidationCheck Ŭ·¡½º ¼Ò½º
public static class ValidationCheck {
public static String CheckValidation(Object data) {
//°´Ã¼ÀÇ Å¸ÀÔ Á¤º¸ Á¶È¸
Type clsType = data.GetType();
//ÇÊµå ¸®½ºÆ® Á¶È¸
FieldInfo [] fields = clsType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetField| BindingFlags.NonPublic);
bool flag = true;
StringBuilder sbuild = new StringBuilder();
foreach (FieldInfo field in fields) {
//ÇʵåÀÇ ¾îÆ®¸®ºäÆ® °Ë»ç
object[] obj = field.GetCustomAttributes(typeof(ValidationTest.ValidationAttribute), true);
if (obj != null && obj.Length > 0) {
ValidationAttribute attr = obj[0] as ValidationTest.ValidationAttribute;
if (attr != null) flag = attr.IsValid(field.GetValue(data).ToString());
if (!flag) sbuild.Append(attr.Msg);
}
}
return sbuild.ToString();
}
}
À̹ø¿¡´Â À¯È¿¼º °Ë»çÀÇ ´ë»óÀÌ µÇ´Â µ¥ÀÌÅÍ Å¬·¡½º¸¦ Ãß°¡ÇØ º¸ÀÚ. Program ÆÄÀÏ¿¡ MyData¶ó´Â Ŭ·¡½º¸¦ Ãß°¡ÇÑ ÈÄ String ŸÀÔÀ¸·Î firstName, lastName, middleNameÀ» ¼±¾ðÇÑ´Ù.
firstName°ú lastName¿¡ Validation ¾îÆ®¸®ºäÆ®¸¦ ¼±¾ðÇÑ ÈÄ¿¡ °¢°¢ÀÇ minLength¿Í maxLength, error ¸Þ½ÃÁö °ªÀ» ºÎ¿©ÇÑ´Ù. °á°ú´Â <¸®½ºÆ® 6>°ú °°´Ù.
<¸®½ºÆ® 6> Program Ŭ·¡½º ¼Ò½º
class Program {
static void Main(string[] args) {
MyData data = new MyData("´ë¿ø", "·ù", "M");
String msg = ValidationCheck.CheckValidation(data);
Console.WriteLine(msg);
}
}
class MyData {
//»ý¼ºÀÚ »ý·«
[Validation(1, 5, "À̸§Àº 4 ÀÚ¸® ÀÌÇÏ¿©¾ß ÇÕ´Ï´Ù.")]
String firstName;
[Validation(1, 2, "¼ºÀº 1ÀÚ¸®¿©¾ß ÇÕ´Ï´Ù.")]
String lastName;
String middleName;
}
½ÇÇàÀ» ½ÃÄÑ º¸¸é MyDataÀÇ firstName°ú lastName °ª¿¡ ´ëÇØ¼ ±ÛÀÚ ¼ö¿¡ ´ëÇÑ À¯È¿¼º °Ë»ç¸¦ ½Ç½ÃÇÏ´Â °ÍÀ» È®ÀÎÇÒ ¼ö ÀÖ´Ù.
¾îÆ®¸®ºäÆ®¸¦ »ç¿ëÇÏÁö ¾Ê´Â´Ù¸é °¢°¢ÀÇ Å¬·¡½º¿¡ ´ëÇÑ À¯È¿¼º °Ë»ç ·ÎÁ÷ÀÌ Å¬·¡½º¿¡ Æ÷ÇԵǰųª ¶Ç´Â °øÅë Äڵ忡 °¢°¢ÀÇ Å¬·¡½ºÀÇ °æ¿ì¸¦ °í·ÁÇØ¼ Ãß°¡µÇ¾î¾ß ÇÑ´Ù.
ÀÌ À¯È¿¼º °Ë»çÀÇ °æ¿ì °£´ÜÇÑ ¿¹À̱⠶§¹®¿¡ MyData¿¡¼ À¯È¿¼º °Ë»ç ·ÎÁ÷À» Ãß°¡ÇØ »ç¿ëÇØµµ Å« ¹«¸®°¡ ¾ø°ÚÁö¸¸ ÇÁ·Î±×·¥ÀÌ Ä¿Áú¼ö·Ï À¯È¿¼º °Ë»ç ºÎºÐ¿¡ ´ëÇÑ ºÎ´ãÀÌ Ä¿Áú ¼ö¹Û¿¡ ¾ø´Ù. ±×·³ ÀÌÁ¦ Á» ´õ º¹ÀâÇÑ ³»¿ë¿¡ ´ëÇÑ ¾îÆ®¸®ºäÆ®ÀÇ È°¿ë¹ý¿¡ ´ëÇØ ¾Ë¾Æº¸ÀÚ.
¾îÆ®¸®ºäÆ®¿Í ¸®Ç÷º¼Ç ¿¡¹Ô(Reflection Emit)À» Ȱ¿ëÇÑ ÇÁ·Î±×·¥ÀÇ È®Àå
ƯÁ¤ ¾îÆ®¸®ºäÆ® °ªÀ» °¡Áö´Â °æ¿ì¿¡ ¸®Ç÷º¼Ç ¿¡¹ÔÀ» ÀÌ¿ëÇØ¼ ÇÁ·Î±×·¥À» È®ÀåÇÏ´Â ¹æ¹ý¿¡ ´ëÇØ¼ »ìÆìº¸ÀÚ.
À̹ø¿¡ ±¸ÇöÇÒ ³»¿ëÀº ¸Þ¼Òµå¿¡ Log¶ó´Â ¾îÆ®¸®ºäÆ®°¡ ÀÖ´Â °æ¿ì ¿ø·¡ ¸Þ¼Òµå¸¦ ½ÇÇàÇϱâ Àü¿¡ ·Î±×¸¦ Ãâ·ÂÇϵµ·Ï ÇÏ´Â ¹æ¹ý¿¡ ´ëÇØ¼ Å×½ºÆ® ÇØº¸µµ·Ï ÇϰڴÙ.
C#À¸·Î console application ÇÁ·ÎÁ§Æ®¸¦ Çϳª »ý¼ºÇÑ´Ù. ÇÁ·ÎÁ§Æ®ÀÇ À̸§Àº LoggingTest·Î Çϰí, LogAttribute Ŭ·¡½º¸¦ Ãß°¡ÇÑ ÈÄ¿¡ Attribute¸¦ »ó¼Ó¹Þ°í AttributeUsageÀÇ Å¸±êÀ¸·Î Method¸¦ ÁöÁ¤ÇÑ´Ù. ÀÌ ¾îÆ®¸®ºäÆ®ÀÇ static ¸Þ¼Òµå·Î Print¸¦ ¼±¾ðÇϰí String °ªÀ¸·Î ¸Þ¼Òµå ¸íÀ» ¹Þ¾Æ¼ ·Î±×¸¦ Ãâ·ÂÇϵµ·Ï ±¸ÇöÇÑ´Ù.
[AttributeUsage(AttributeTargets.Method)]
public class LogAttribute : Attribute {
public static void Print(String methodInfo) {
Console.WriteLine("Call " + methodInfo);}
}
Program ÆÄÀÏ¿¡ ÀÎÅÍÆäÀ̽º·Î IBizService¸¦ ¼±¾ðÇÑ ÈÄ¿¡ ProcessData¿Í ProcessData2¸¦ ¼±¾ðÇÑ´Ù. BizService Ŭ·¡½º¸¦ ¼±¾ðÇϰí ProcessData¿Í ProcessData2 ¸Þ¼Òµå¸¦ ±¸ÇöÇÑ´Ù. Main ¸Þ¼Òµå¿¡¼ IBizService °´Ã¼¸¦ »ý¼ºÇÑ ÈÄ¿¡ ProcessData¸¦ È£ÃâÇϵµ·Ï ±¸ÇöÇÑ´Ù. IBizService °´Ã¼ »ý¼º ½Ã ServiceLocator¸¦ ÅëÇØ¼ »ý¼ºÇϵµ·Ï ÇÑ´Ù. ±¸Çö °á°ú´Â <¸®½ºÆ® 7>°ú °°´Ù.
<¸®½ºÆ® 7> Program Ŭ·¡½º ¼Ò½º
public class Program {
static void Main(string[] args) {
//ServiceLocator¸¦ ÅëÇØ¼ °´Ã¼ »ý¼º
IBizService service = (IBizService)ServiceLocator.getObject("LoggingTest.BizService","LoggingTest.IBizService" );
//Log ¾îÆ®¸®ºäÆ®¸¦ »ç¿ëÇÑ °æ¿ì
String str = service.ProcessData("my value");
Console.WriteLine(str);
//Log ¾îÆ®¸®ºäÆ®¸¦ »ç¿ëÇÏÁö ¾Ê´Â °æ¿ì
String str2 = service.ProcessData2("my value1","my value2");
Console.WriteLine(str2);}
}
//ÀÎÅÍÆäÀ̽º Á¤ÀÇ »ý·«
public class BizService : IBizService {
[Log]
public String ProcessData(string data) {
return data + " has been processed!!!"; }
public String ProcessData2(string data1, String data2) {
return data1 + " and " +data2 + " have been processed!!!"; }
}
ServiceLocator Ŭ·¡½º¸¦ Ãß°¡ÇÑ ÈÄ¿¡ static ¸Þ¼Òµå·Î GetObject¸¦ »ý¼ºÇÑ´Ù. GetObjectÀÇ ÆÄ¶ó¹ÌÅͷδ ŸÀÔ ¸í°ú ÀÎÅÍÆäÀ̽º ¸íÀ» ¹Þµµ·Ï ¼±¾ðÇÑ´Ù. ¸Þ¼Òµå¿¡¼´Â ÇØ´ç ŸÀÔ ¸í°ú ÀÎÅÍÆäÀ̽º ¸íÀ» ÀÌ¿ëÇØ °´Ã¼ÀÇ ÇÁ·Ï½Ã(proxy)¸¦ »ý¼ºÇϵµ·Ï ÇÑ´Ù.
ÀÌ ÇÁ·Ï½Ã °´Ã¼´Â Log ¾îÆ®¸®ºäÆ®°¡ ¼±¾ðµÇ¾î ÀÖ´Â °æ¿ì ¸®Ç÷º¼Ç ¿¡¹ÔÀ» ÀÌ¿ëÇØ ·Î±×¸¦ Ãâ·ÂÇÏ´Â Äڵ尡 Æ÷ÇÔµÈ °´Ã¼¸¦ »ý¼ºÇØ ³»µµ·Ï ±¸ÇöÇÑ´Ù.
¿ì¼± ÇöÀç ¾²·¹µå¸¦ ÀÌ¿ëÇØ ¾î¼Àºí¸® ºô´õ¸¦ »ý¼ºÇÑ ÈÄ ¸ðµâ ºô´õ¸¦ »ý¼ºÇÏ°í ´Ù½Ã ÀÌ ¸ðµâ ºô´õ¸¦ ÀÌ¿ëÇØ ŸÀÔ ºô´õ¸¦ »ý¼ºÇÑ´Ù. ŸÀÔ ºô´õ »ý¼º ½Ã Object °´Ã¼¸¦ »ó¼Ó¹Þ°í ÆÄ¶ó¹ÌÅÍ·Î ¹ÞÀº ÀÎÅÍÆäÀ̽º ŸÀÔÀ» ±¸ÇöÇϵµ·Ï ÇÑ´Ù.
TypeBuilder tb = mb.DefineType("myType", TypeAttributes.Public | TypeAttributes.Class, typeof(Object), new Type[] { interfaceType });
ŸÀÔ ºô´õ¸¦ ÀÌ¿ëÇØ ¸Þ¼Òµå ºô´õ¸¦ »ý¼ºÇÑ´Ù. ¸Þ¼Òµå ¾îÆ®¸®ºäÆ®´Â public°ú virtualÀ» ÁöÁ¤Çϰí return ŸÀÔ°ú ÆÄ¶ó¹ÌÅÍ Å¸ÀÔÀ» ÁöÁ¤ÇÑ´Ù.
MethodBuilder methodbuilder = tb.DefineMethod(methodInfo.Name, MethodAttributes.Public | MethodAttributes.Virtual, methodInfo.ReturnType, types);
¸Þ¼Òµå ºô´õ¸¦ ÀÌ¿ëÇØ IL Äڵ带 »ý¼ºÇÒ ¼ö ÀÖ´Â ILGenerator¸¦ »ý¼ºÇÑ´Ù. ¸Þ¼Òµå¿¡ Log ¾îÆ®¸®ºäÆ®°¡ ¼±¾ðµÇ¾î ÀÖ´Â °æ¿ì ·Î±×¸¦ Ãâ·ÂÇÏ´Â IL Äڵ带 »ðÀÔÇÑ ÈÄ¿¡ ¿ø·¡ÀÇ ¸Þ¼Òµå¸¦ È£ÃâÇÏ´Â Äڵ带 »ý¼ºÇÑ´Ù.
ŸÀÔ ºô´õ¸¦ ÅëÇØ ŸÀÔÀ» »ý¼ºÇÑ ÈÄ Activator¸¦ ÀÌ¿ëÇØ »ý¼ºÇÑ °´Ã¼¸¦ ¸®ÅÏÇÏ¸é µÈ´Ù. ±¸Çö °á°ú´Â <¸®½ºÆ® 8>°ú °°À¸¸ç Spring.NETÀÇ AOP ºÎºÐÀÌ ´ÙÀ½°ú °°ÀÌ ¸®Ç÷º¼Ç ¿¡¹ÔÀ» ÀÌ¿ëÇÏ¿© ±¸ÇöµÇ¾î ÀÖ´Ù.
<¸®½ºÆ® 8>ServiceLocator Ŭ·¡½º ¼Ò½º
static class ServiceLocator {
//caching °ü·Ã ³»¿ë »ý·«
public static Object getObject(String typeName, String interfaceName) {
//¸Þ¼Òµå ÀϺΠ³»¿ë »ý·«(»ó¼¼ÇÑ ³»¿ëÀ» ÀÌ´ÞÀÇ µð½ºÄÏ ÂüÁ¶)
Type clsType = Type.GetType(typeName);
Type interfaceType = clsType.GetInterface(interfaceName);
MethodInfo[] methodInfos = clsType.GetMethods();
AssemblyBuilder ab = Thread.GetDomain().DefineDynamicAssembly(new AssemblyName("myAsm"), AssemblyBuilderAccess.Run);
ModuleBuilder mb = ab.DefineDynamicModule("myMod");
TypeBuilder tb = mb.DefineType("myType", TypeAttributes.Public | TypeAttributes.Class, typeof(Object), new Type[] { interfaceType });
foreach (MethodInfo methodInfo in methodInfos) {
MethodBuilder methodbuilder = tb.DefineMethod(methodInfo.Name, MethodAttributes.Public | MethodAttributes.Virtual, methodInfo.ReturnType, types);
ILGenerator il = methodbuilder.GetILGenerator();
//Log ¾îÆ®¸®ºäÆ®°¡ ¼±¾ðµÈ °æ¿ì Ãâ·ÂÀ» À§ÇÑ ÄÚµå »ðÀÔ
object[] myAttributes = methodInfo.GetCustomAttributes(typeof(LoggingTest.LogAttribute), false)
if (myAttributes != null && myAttributes.Length > 0) {
LogInterceptor(methodInfo, il, (Attribute)myAttributes[0]);}
//¿ø·¡ °´Ã¼ÀÇ ¸Þ¼Òµå¸¦ È£ÃâÇϱâ À§ÇÑ ºÎºÐ
il.Emit(OpCodes.Nop);
il.Emit(OpCodes.Newobj, clsType.GetConstructor(System.Type.EmptyTypes));
for (int i = 1; i <= types.Length; i++) {
il.Emit(OpCodes.Ldarg_S, i); }
il.Emit(OpCodes.Callvirt, methodInfo);
il.Emit(OpCodes.Ret); }
Type t = tb.CreateType();
//°´Ã¼ »ý¼º
Object instance = Activator.CreateInstance(t);
return instance;
}
private static void LogInterceptor(MethodInfo methodInfo, ILGenerator il, Attribute attribute) {
LoggingTest.LogAttribute attr = (LoggingTest.LogAttribute) attribute
il.Emit(OpCodes.Ldstr, methodInfo.Name);
il.Emit(OpCodes.Call, attr.GetType().GetMethod("Print", BindingFlags.Static | BindingFlags.Public)); }
}}
Âü°í·Î IL Äڵ带 »ý¼ºÇÏ´Â °æ¿ì ÄÄÆÄÀÏ ½Ã¿¡ ¿¡·¯¿¡ ´ëÇÑ È®ÀÎÀ» ÇÒ ¼ö ¾øÀ¸¸ç, ·±Å¸ÀÓ ½Ã¿¡µµ ¿¡·¯ ¸Þ½ÃÁö°¡ µµ¿òÀÌ ¾ÈµÇ´Â °æ¿ì°¡ ¸¹´Ù. IL Äڵ带 ÀÛ¼ºÇÒ ¶§¿¡´Â ¾î¼Àºí¸®¸¦ ÆÄÀÏ·Î ÀúÀåÇÑ ÈÄ¿¡(ÆÄÀÏ¿¡ ÀúÀåÇÏ´Â ÄÚµå´Â ÀÌ´ÞÀÇ µð½ºÄÏ¿¡ ÁÖ¼® ó¸® µÇ¾î ÀÖÀ½) »ý¼ºµÈ ÆÄÀÏÀ» reflector¿Í PEVerify¶ó´Â ÄÜ¼Ö ¸í·ÉÀ» ÀÌ¿ëÇØ °Ë»çÇØ º¸´Â ¹æ¹ýÀ» »ç¿ëÇÑ´Ù.
Áö±Ý±îÁö ¾îÆ®¸®ºäÆ® ¿À¸®¿£Æ¼µå ÇÁ·Î±×·¡¹Ö ±â¹ýÀ» Ȱ¿ëÇÏ´Â ¹æ¹ý¿¡ ´ëÇØ¼ »ìÆìº¸¾Ò´Ù. ¾îÆ®¸®ºäÆ®´Â Ȱ¿ëÇÏ´Â ¹æ¹ý¿¡ µû¶ó È®À强ÀÌ ¸Å¿ì ³ôÀ¸¸ç ¸Å¿ì À¯¿ëÇÏ°Ô »ç¿ëµÉ ¼ö ÀÖ´Ù. ¹°·Ð ¾îÆ®¸®ºäÆ® Ȱ¿ë ½Ã ¸®Ç÷º¼ÇÀ» ¸¹ÀÌ »ç¿ëÇÏ°Ô µÇ¸é ¿À¹öÇìµå°¡ ÀÖÀ¸¹Ç·Î Àû´çÇÑ ¼öÁØ¿¡¼ »ç¿ëÇØ¾ß ÇÑ´Ù.
À̹ø Ä®·³ÀÌ µ¶ÀÚ ¿©·¯ºÐ¿¡°Ô ¾îÆ®¸®ºäÆ®¿¡ ´ëÇÑ ÀÌÇØ¿Í ´å³Ý¿¡¼ÀÇ Àû¿ë¿¡ µµ¿òÀÌ µÇ¾ú±â¸¦ ¹Ù¶ó¸é¼ ÀÌ ±ÛÀ» ¸¶Ä£´Ù. @
ÀϹÝÀûÀ¸·Î ¸®Ç÷º¼Ç°ú ¸®Ç÷º¼Ç ¿¡¹ÔÀ» È¥µ¿ÇÏ´Â °æ¿ì°¡ ¸¹Àºµ¥ ¸®Ç÷º¼ÇÀÇ ¿ëµµ´Â ¸ÞŸµ¥ÀÌÅͳª ŸÀÔ Á¤º¸¸¦ Á¶È¸Çϰųª µ¿ÀûÀ¸·Î ¸Þ¼Òµå¸¦ È£ÃâÇϴµ¥ »ç¿ëÀÌ µÈ´Ù. ¹Ý¸é¿¡ ¸®Ç÷º¼Ç ¿¡¹ÔÀº ·±Å¸ÀÓ ½Ã¿¡ ¸ÞŸµ¥ÀÌÅÍ¿Í IL Äڵ带 »ý¼ºÇϰųª ¹°¸®ÀûÀÎ Portable Executable(PE) ÆÄÀÏ·Î ÀúÀåÇÏ´Â µîÀÇ Á» ´õ °·ÂÇÑ ±â´ÉÀÌ ÇÊ¿äÇÒ ¶§ »ç¿ëµÈ´Ù.
¸®Ç÷º¼Ç ¿¡¹ÔÀ» »ç¿ëÇϱâ À§Çؼ´Â ¿ì¼± ¾î¼Àºí¸® ºô´õ¸¦ »ý¼ºÇØ¾ß Çϴµ¥ ÇöÀç ¾²·¹µåÀÇ ¾îÇø®ÄÉÀÌ¼Ç µµ¸ÞÀÎÀ» ¾òÀº ÈÄ ÇöÀç µµ¸ÞÀÎ °´Ã¼ÀÇ DefineDynamicAssembly ¸Þ¼Òµå¸¦ È£ÃâÇÑ´Ù.
¸Þ¼ÒµåÀÇ ÆÄ¶ó¹ÌÅͷδ ¾î¼Àºí¸® ¸íÀ» ÁöÁ¤ÇÏ´Â AssemblyName °´Ã¼¿Í »ý¼ºµÈ ¾î¼Àºí¸®¿¡ ´ëÇÑ ½ÇÇà(Run), ÀúÀå(Save) µîÀÇ Á¢±Ù Á¦¾î °ªÀÎ AssemblyBuilderAccess enum °ªÀ» Àü´ÞÇÑ´Ù.
AssemblyName assemblyName = new AssemblyName("myAssembly");
AssemblyBuilder assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
»ý¼ºµÈ ¾î¼Àºí¸® ºô´õÀÇ DefineDynamicModuleÀ» ÀÌ¿ëÇØ ¸ðµâ ºô´õ¸¦ »ý¼ºÇÑ´Ù. ÆÄ¶ó¹ÌÅͷδ ¸ðµâ¸í°ú ÆÄÀÏ·Î »ý¼ºÇÏ´Â °æ¿ì »ý¼ºÇÒ ÆÄÀϸíÀ» Àü´ÞÇÑ´Ù.
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("myModule", "myModule.dll");
ÀÌÁ¦ °¡Àå Áß¿äÇÑ Å¸ÀÔ ºô´õ¸¦ »ý¼ºÇÒ Â÷·Ê´Ù. ¸¶Âù°¡Áö·Î ¸ðµâ ºô´õÀÇ DefineType ¸Þ¼Òµå¸¦ ÀÌ¿ëÇØ¼ »ý¼ºÇÑ´Ù. ÆÄ¶ó¹ÌÅͷδ ŸÀÔ¸í°ú ŸÀÔÀÇ Á¢±ÙÀÚ, ŸÀÔÀÇ ºÎ¸ð Ŭ·¡½º, ±¸Çö ÀÎÅÍÆäÀ̽º¸¦ Àü´ÞÇÑ´Ù.
TypeBuilder typeBuilder = moduleBuilder.DefineType("myType", TypeAttributes.Public | TypeAttributes.Class, typeof(Object), new Type[0]);
ÀÌ Å¸ÀÔ ºô´õ¸¦ ÀÌ¿ëÇØ »ý¼ºÀÚ, À̺¥Æ®, Çʵå, ¸Þ¼Òµå µî Ŭ·¡½º¿¡ Á¤ÀÇÇØ¾ß ÇÏ´Â ´Ù¾çÇÑ ¿ä¼ÒµéÀ» Á¤ÀÇÇÒ ¼ö ÀÖ´Ù.
¿ì¼± »ý¼ºÀÚ¸¦ ¸¸µé¾î º¸¸é ´ÙÀ½°ú °°ÀÌ Å¸ÀÔ ºô´õÀÇ DefineConstructor ¸Þ¼Òµå¸¦ È£ÃâÇØ¼ »ý¼ºÇÑ´Ù. ÆÄ¶ó¹ÌÅͷδ »ý¼ºÀÚÀÇ Á¢±ÙÀÚ¿Í È£Ãâ ±Ô¾à, ÆÄ¶ó¹ÌÅÍ °ªÀ» Àü´ÞÇÑ´Ù.
ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new Type[0]);
»ý¼ºÀÚ ºô´õ·ÎºÎÅÍ ILGenerator¸¦ »ý¼ºÇÑ´Ù. ÀÌ ILGenerator¸¦ ÀÌ¿ëÇØ¼ ½ÇÁ¦ IL Äڵ带 ÀÛ¼ºÇÏ°Ô µÈ´Ù.
ILGenerator ilGenerator = constructorBuilder.GetILGenerator();
ºñ½ÁÇÑ ¹æ¹ýÀ¸·Î ¸Þ¼Òµå ºô´õ´Â ´ÙÀ½°ú °°ÀÌ »ý¼ºÇÑ´Ù. ÆÄ¶ó¹ÌÅͷδ ¸Þ¼Òµå¸í°ú ¸Þ¼Òµå Á¢±ÙÀÚ, È£Ãâ ±Ô¾à, ÆÄ¶ó¹ÌÅÍ °ªÀ» Àü´ÞÇÑ´Ù.
MethodBuilder methodBuilder = typeBuilder.DefineMethod("TestMethod", MethodAttributes.Public | MethodAttributes.Virtual, CallingConventions.HasThis, methodInfo.ReturnType, types);
ILGenerator ilGenerator = methodBuilder.GetILGenerator();
Çʵ带 »ý¼ºÇÒ ¶§´Â ´ÙÀ½°ú °°ÀÌ DefineField¿¡ Çʵå¸í°ú ŸÀÔ, Çʵå Á¢±ÙÀÚ °ª¸¸ Àü´ÞÇÏ¸é µÇ°í IL ÄÚµå´Â ÇÊ¿ä ¾ø´Ù.
FieldBuilder fieldBuilder = typeBuilder.DefineField("name", typeof(String), FieldAttributes.Private);
IL Äڵ带 »ý¼ºÇÏ´Â ºÎºÐ¿¡ ´ëÇØ¼´Â Àá½Ã µÚ·Î ¹Ì·ç°í ŸÀÔ¿¡ ´ëÇÑ ÀÛ¼ºÀÌ ¿Ï·á°¡ µÇ¸é ŸÀÔ ºô´õÀÇ CreateType ¸Þ¼Òµå¸¦ È£ÃâÇØ¼ ŸÀÔÀ» »ý¼ºÇÑ ÈÄ ÀúÀåÀÌ ÇÊ¿äÇÑ °æ¿ì ¾î¼Àºí¸® ºô´õÀÇ Save ¸Þ¼Òµå¸¦ È£ÃâÇØ ÀúÀåÇÑ´Ù. ÁÖÀÇÇÒ »çÇ×Àº CreateType ¸Þ¼Òµå È£Ãâ ÀÌÈÄ¿¡´Â ŸÀÔ¿¡ ´ëÇÑ º¯°æÀÌ ºÒ°¡´ÉÇÏ´Ù´Â Á¡ÀÌ´Ù.
Type t = typeBuilder.CreateType();
assemblyBuilder.Save("test.dll");
ÀÌÁ¦ IL Äڵ带 ÀÛ¼ºÇÏ´Â ¹æ¹ý¿¡ ´ëÇØ¼ »ìÆìº¸ÀÚ. IL Äڵ带 ÀÛ¼ºÇϱâ À§Çؼ´Â IL À̶ó´Â ¾î¼Àºí¸®¿Í À¯»çÇÑ ¾ð¾î¸¦ ¹è¿ö¾ß ÇÑ´Ù. ¹°·Ð ¾î¼Àºí¸®¿Í °°Àº low level ¾ð¾î¸¦ ¾Ë¾Æ µÎ´Â °Íµµ ¾î¶² ¸é¿¡¼´Â À¯¿ëÇϰÚÁö¸¸ Áö±Ý ´çÀå ÇÊ¿äÇÏÁöµµ ¾ÊÀ»»Ó´õ·¯ ÇâÈÄ¿¡µµ »ç¿ëÇÒ ÀÌÀ¯°¡ º°·Î ¾øÀ» °Í °°Àº ¾ð¾î¸¦ ¿½ÉÈ÷ °øºÎÇÑ´Ù´Â °ÍÀº ¸Å¿ì ±ÍÂúÀº(?) ÀÏÀ̹ǷΠ´Ù¸¥ ¹æ¹ýÀ» ã¾Æº¸ÀÚ. º»¹®¿¡¼ »ç¿ëÇß´ø µµ±¸ÀÎ ildasmÀ» Ȱ¿ëÇØ º¸ÀÚ.
±¸ÇöÇÏ·Á°í ÇÏ´Â ³»¿ëÀ» C#À¸·Î ÀÛ¼ºÇÑ ÈÄ ÄÄÆÄÀÏ µÈ IL Äڵ带 Á¶È¸ÇØ ÀÌ Äڵ带 Âü°íÇØ¼ ¿ì¸®°¡ ÀÛ¼ºÇÏ·Á´Â ³»¿ë¿¡ ´ëÇÑ IL Äڵ带 ÀÛ¼ºÇϸé Á» ´õ ½±°Ô ±¸ÇöÇÒ ¼ö ÀÖ´Ù.
¿¹¸¦ µé¾î ¿ì¸®°¡ ÀÛ¼ºÇÏ·Á´Â ³»¿ëÀÌ <¸®½ºÆ® 9>¿Í °°Àº ÄÚµå¶ó°í Çϸé Äڵ带 ÄÄÆÄÀÏ ÇÑ ÈÄ ildasm ¸í·É¾î¸¦ ÅëÇØ Á¶È¸ÇØ º¸¸é <¸®½ºÆ® 10> °°Àº IL ÄÚµå ³»¿ëÀ» È®ÀÎÇÒ ¼ö ÀÖ°Ú´Ù.
<¸®½ºÆ® 9> ±¸ÇöÇÏ·Á´Â Ŭ·¡½ºÀÇ »ý¼ºÀÚ ¼Ò½º
public MyTest(String name) {
this.name = name;
}
<¸®½ºÆ® 10> »ý¼ºµÈ »ý¼ºÀÚ IL ÄÚµå
.method public hidebysig specialname rtspecialname
instance void .ctor(string name) cil managed
{
// Code size 17 (0x11)
.maxstack 8
IL_0000: ldarg.0 (1)
IL_0001: call instance void [mscorlib]System.Object::.ctor() (2)
IL_0006: nop
IL_0007: nop
IL_0008: ldarg.0 (3)
IL_0009: ldarg.1 (4)
IL_000a: stfld string LoggingTest.MyTest::name (5)
IL_000f: nop
IL_0010: ret (6)
} // end of method MyTest::.ctor
IL Äڵ带 »ìÆìº¸¸é ù ¹øÂ° ÆÄ¶ó¹ÌÅÍ °ªÀ» ½ºÅÃÀ¸·Î ·ÎµåÇÑ(1) ÈÄ ºÎ¸ð Ŭ·¡½ºÀÎ ObjectÀÇ »ý¼ºÀÚ¸¦ È£Ãâ(2)ÇÑ´Ù. µÎ ¹øÂ° ÆÄ¶ó¹ÌÅÍÀÎ string °ªÀ» ½ºÅÿ¡ ·ÎµåÇÑ(4) ÈÄ nameÀ̶ó´Â Çʵ忡 °ªÀ» ÇÒ´ç(5)ÇÑ ÈÄ¿¡ ¸®ÅÏ(6)ÇÑ´Ù. ¿ì¸®°¡ C# Äڵ忡¼ ÀÛ¾÷ÇØ ÁØ ³»¿ëÀº »ý¼ºÀÚ¿¡¼ name Çʵ忡 ÆÄ¶ó¹ÌÅÍ·Î Àü´Þ¹ÞÀº º¯¼ö¸¦ ÇÒ´çÇÑ °Í ¹Û¿¡ ¾ø´Âµ¥ IL Äڵ忡¼´Â ³»ºÎÀûÀ¸·Î ÀÌ·¸°Ô »ó´ëÀûÀ¸·Î ¸¹Àº Äڵ尡 »ý¼ºÀÌ µÇ´Â °ÍÀÌ´Ù.
IL ÄÚµå ÀÛ¼º ½Ã ÁÖÀÇÇÒ »çÇ×Àº »ý¼ºÀÚ ÀÛ¼º ½Ã ¹Ýµå½Ã ºÎ¸ð Ŭ·¡½ºÀÇ »ý¼ºÀÚ¸¦ ¸í½ÃÀûÀ¸·Î È£ÃâÇØ ÁÖ¾î¾ß ÇÑ´Ù´Â Á¡°ú ½ºÅÂÆ½ÀÌ ¾Æ´Ñ ¸Þ¼ÒµåÀÇ ÆÄ¶ó¹ÌÅÍ·Î Àü´ÞµÇ´Â °ªÀÇ Ã¹ ¹øÂ°´Â ¹Ýµå½Ã ÇØ´ç ¸Þ¼Òµå°¡ ¼ÓÇÑ °´Ã¼¿¡ ´ëÇÑ ÂüÁ¶À̾î¾ß ÇÑ´Ù´Â Á¡ÀÌ´Ù. Áï this °´Ã¼¿¡ ´ëÇÑ ÂüÁ¶°¡ µÇ°Ú´Ù.
<¸®½ºÆ® 10>ÀÇ »ý¼ºÀÚ Äڵ带 Âü°íÇØ¼ IL Äڵ带 ÀÛ¼ºÇØ º¸¸é <¸®½ºÆ® 11>°ú °°ÀÌ µÈ´Ù. ldarg.0 ÄÚµå´Â OpCodes.Ldarg_0°ú ¸ÅÇεǰí call ÄÚµå´Â Opcodes.Call, stfld ÄÚµå´Â Opcodes.Stsfld¿Í ¸ÅÇεȴÙ. Opcodes.Call°ú Opcodes.StsfldÀÇ µÎ ¹øÂ° ÆÄ¶ó¹ÌÅͷδ °¢°¢ ConstructorInfo, FieldInfo °´Ã¼°¡ µÇ°Ú´Ù.
FieldInfo Ŭ·¡½º°¡ FieldBuilderÀÇ ºÎ¸ð Ŭ·¡½ºÀ̹ǷΠFieldInfo ´ë½Å FieldBuilder °ªÀ» Àü´ÞÇÑ´Ù.
<¸®½ºÆ® 11> ÀÛ¼ºÇÑ IL ÄÚµå
//»ý¼ºÀÚ
ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(
MethodAttributes.Public,
CallingConventions.Standard,
new Type[] {typeof(string)});
ILGenerator ilGenerator = constructorBuilder.GetILGenerator();
ConstructorInfo conObj = typeof(object).GetConstructor(new Type[0]);
//ºÎ¸ð Ŭ·¡½º »ý¼ºÀÚ È£Ãâ
ilGenerator.Emit(OpCodes.Ldarg_0);
ilGenerator.Emit(OpCodes.Call, conObj);
//Çʵ忡 °ª ÇÒ´ç
ilGenerator.Emit(OpCodes.Ldarg_0);
ilGenerator.Emit(OpCodes.Ldarg_1);
ilGenerator.Emit(OpCodes.Stsfld, fieldBuilder);
ilGenerator.Emit(OpCodes.Ret);
ÀÛ¼ºµÈ Äڵ尡 Á¤»óÀÎÁö È®ÀÎÇϱâ À§Çؼ´Â ¾î¼Àºí¸® ÆÄÀÏÀ» »ý¼ºÇÑ ÈÄ¿¡ »ý¼ºµÈ ¾î¼Àºí¸® ÆÄÀÏÀ» reflector¸¦ ÀÌ¿ëÇØ Á¶È¸ÇØ º¸¸é ÀÌ»óÀÌ ¾ø´Â °æ¿ì Á¤»óÀûÀ¸·Î µðÄÄÆÄÀÏÀÌ µÈ´Ù.
ÀÌ»ó°ú °°ÀÌ ¸®Ç÷º¼Ç ¿¡¹Ô¿¡ ´ëÇÑ »ç¿ë ¹æ¹ý¿¡ ´ëÇØ¼ °£´ÜÈ÷ »ìÆìº¸¾Ò´Ù. ¸®Ç÷º¼Ç ¿¡¹ÔÀÇ °æ¿ì ¸®Ç÷º¼Ç¿¡ ºñÇØ¼ ¼º´É ¸éÀ̳ª È®À强 ¸é¿¡¼ ¸Å¿ì ¿ì¼öÇÏÁö¸¸ IL Äڵ忡 ´ëÇÑ ÀÛ¼º ºÎºÐÀÌ ½±Áö ¾Ê¾Æ ¸¹ÀÌ »ç¿ëµÇÁö ¾Ê°í ÀÖ´Ù. ÇÏÁö¸¸ ¸®Ç÷º¼Ç ¿¡¹Ô »ç¿ë ½Ã ÀϹÝÀûÀ¸·Î ±¸ÇöÇϱâ Èûµç ´Ù¾çÇÑ µ¿Àû ÇÁ·Î±×·¡¹ÖÀÌ °¡´ÉÇÏ´Ï ±âȸ°¡ µÇ¸é Àû¿ëÇØ º¸±æ ¹Ù¶õ´Ù.
¶ÇÇÑ ´å³Ý 2.0¿¡ »õ·Ó°Ô Ãß°¡µÈ µ¿Àû ¸Þ¼Òµå(Dynamic Method) ±â¹ýÀ» ÀÌ¿ëÇÏ°Ô µÇ¸é ¾î¼Àºí¸®¸¦ ºôµåÇÏÁö ¾Ê°íµµ µ¿ÀûÀ¸·Î ¸Þ¼Òµå¸¦ È£ÃâÇÒ ¼ö ÀÖ¾î¼ Á» ´õ Çâ»óµÈ ¼º´É ¹× À¯Áöº¸¼ö¼ºÀ» ¾òÀ» ¼ö ÀÖ°Ú´Ù. °£´ÜÇÑ Dynamic Method ¿¹Á¦´Â ÀÌ´ÞÀÇ µð½ºÄÏÀ» ÂüÁ¶Çϱ⠹ٶõ´Ù.
Âü°íÀÚ·á
1. Attributes in C# - http://www.codeproject.com/csharp/attributes.asp
2. Introduction to Creating Dynamic Types with Reflection.Emit - http://www.codeproject.com/useritems/Creating_Dynamic_Types2.asp
* ÀÌ ±â»ç´Â ZDNet KoreaÀÇ Á¦ÈÞ¸ÅüÀÎ ¸¶ÀÌÅ©·Î¼ÒÇÁÆ®¿þ¾î ¿¡ °ÔÀçµÈ ³»¿ëÀÔ´Ï´Ù.
°ü·Ã±â»ç
µ¶ÀÚÀÇ°ß ³²±â±â (·Î±×ÀÎ ÈÄ µ¶ÀÚ ÀǰßÀ» ³²±â½Ç ¼ö ÀÖ½À´Ï´Ù.)