Autofac IoC / DIã³ã³ããã®èè
ã§ããæåãª.NETéçºè
ã§ããNicholas Bloomhardtã«ããèšäºã®ç¿»èš³ã ãã®èšäºã§ã¯ãNicholasãå®éã®äŸã䜿çšããŠãããŒãµãŒã³ã³ãããŒã¿ãŒã®ã©ã€ãã©ãªã§ããSpracheã䜿çšããŠãæå°éã®åŽåã§ãµããžã§ã¯ãæåããã°ã©ãã³ã°èšèªã®ããŒãµãŒãäœæããæ¹æ³ã瀺ããŸãã
çŸåšã®ãããžã§ã¯ãã«ã¯ããŠãŒã¶ãŒã¢ã«ãŠã³ããäœæããããã®ã¢ããªã±ãŒã·ã§ã³ãéä¿¡ããã³æ¿èªããããã®å°ããªããã»ã¹ãå«ãŸããŠããŸãã ããã¯ããã¡ã€ã³åºæã®èšèªãš
Spracheãè°è«ããè¯ãäŸã§ãã 次ã«ãããã€ãã®èŠä»¶ã«ã€ããŠèª¬æããŸãã
ãŠãŒã¶ãŒã¢ã«ãŠã³ãã®çš®é¡ã®ã»ããã¯ç¡å¶éã§ãã çŸåšã¯ããåŸæ¥å¡ãããè«è² æ¥è
ããã掟é£ç€Ÿå¡ããªã©ã§ãã ã¢ã«ãŠã³ããååŸããã«ã¯ããŠãŒã¶ãŒã¯é©åãªãã©ãŒã ã«å
¥åããå¿
èŠããããŸãã
ã¢ã³ã±ãŒãã®ããŒã¿ãåéããŠä¿åããå Žåãé¢é£ããæ
å ±ã管çè
ã«æ瀺ããããŸã§ããã®å
容ã¯éèŠã§ã¯ãããŸããã管çè
ã¯æçµçã«ã¢ããªã±ãŒã·ã§ã³ãæ¿èªãŸãã¯æåŠããŸãã
VS2010ã®ãœãªã¥ãŒã·ã§ã³ã®åœ¢åŒã®äŸãžã®ãªã³ã¯ãé£ãã
å€ãã®ç¹ã§ãã·ã¹ãã ã®èšèšã¯ãå¯èœãªã¿ã€ãã®ã¢ã«ãŠã³ãã®ã»ããïŒãããã£ãŠãããŸããŸãªãããã¡ã€ã«ïŒãç¡å¶éã§ãããšããäºå®ã«ãããã®ã§ãã ã¢ããªã±ãŒã·ã§ã³ãåãããã€ããªããŠããæ°ãããããã¡ã€ã«ãäœæã§ããã¯ãã§ãã ããã«ãã¢ã³ã±ãŒãã®æ§æã¯ããšã³ããŠãŒã¶ãŒèªèº«ãç°¡åã«å€æŽã§ããå¿
èŠããããŸãã
ãããã¡ã€ã«ãéä¿¡ããã«ã¯å€ãã®æ¹æ³ããããŸãã
- ã¢ã³ã±ãŒãã®ãã¡ã€ã³ã¢ãã«ããªã¬ãŒã·ã§ãã«ããŒã¿ããŒã¹ããŒãã«ã«ããããã
- XMLããŒã¹ã®ã¢ã³ã±ãŒã圢åŒãäœæãã
- äžè¬çãªXAMLãã¡ã€ã«ã§Windows Workflow Foundationã䜿çšãã
- CSVãã¡ã€ã«ãŸãã¯ä»ã®ããŒãã«ãããããã¡ã€ã«ãèªã¿åã
ãããã®åã¡ãœããã«ã¯ãå®è£
ã®å®¹æããä¿å®æ§ãå©äŸ¿æ§ãããã³æè»æ§ã«é¢é£ããé·æãšçæããããŸãã
ãã®èšäºã§ã¯ãå¥ã®é
åçãªãªãã·ã§ã³ãæ€èšããŸãããããã¡ã€ã«ãèšè¿°ããããã®äŸ¿å©ãªããèšèªãäœæããŸãã
ãããã¡ã€ã«èšè¿°èšèª
å
éšDSLãšå€éšDSLã®éãã«ã€ããŠã®è°è«ãèªãã ããšããããããããŸããã
å
éš DSLã¯æ±çšèšèªïŒCïŒãªã©ïŒã®å°çšAPIã§ããã䜿çšãããš
ãåé¡ã解決ããããã°ã©ã ãšããŠã§ã¯ãªã
ãåé¡ã®èª¬æãšããŠèªãŸ
ããŸãã
å€éš DSLã¯ãããã°ã©ã ãåäœããåã«ãœãŒã¹ã³ãŒããã解æããå¿
èŠãããå¥åã®èšèªã§ãã ãŸããããã¯ç§ãã¡ã®ã¿ã¹ã¯ã«ãšã£ãŠç¹ã«éèŠã§ãããå€éšDSLã¯æå°éã®æ§æãã€ãºã«å¯äžããããã°ã©ã ãåã³ã³ãã€ã«ããã«èªã¿åãããšãã§ããŸãã
DSLã¢ã³ã±ãŒãã®äŸã¯æ¬¡ã®ããã«ãªããŸãã
identification "Personal Details" [ name "Full Name" department "Department" ] employment "Current Employer" [ name "Your Employer" contact "Contact Number" #months "Total Months Employed" ]
ããã¯ãå人ããŒã¿ãšéçšã®è©³çŽ°ãåéãã2段éã®ã¢ã³ã±ãŒãã§ãã
- åã»ã¯ã·ã§ã³ã«ã¯ãç¬èªã®èå¥åãã¿ã€ãã«ã質åã®ãªã¹ãããããŸãã
- å質åã«ã¯èå¥åãšç¹å®ã®ã¯ãšãªããã¹ãããããŸãã
- 質åèå¥åã®å®£èšïŒããšãã°ãïŒmonthsïŒã«ã¯ãåéãããããŒã¿ã®ã¿ã€ãã瀺ãèšå·ããã®æ¥é èŸãå«ãŸããå ŽåããããŸã-ãã®å Žåã®ãã³ãèšå·ã¯èªç¶æ°ã瀺ããŸãã
ã¢ããªã±ãŒã·ã§ã³ã¯ã察å¿ããçš®é¡ã®ã¢ã«ãŠã³ãã«é¢é£ä»ããããã¢ã³ã±ãŒãã®èª¬æãèªã¿åãããŠãŒã¶ãŒã«æ®µéçãªã€ã³ã¿ãŒãã§ã€ã¹ãæ瀺ããŸãã
ãããã¡ã€ã«ã®èšè¿°ã®åæãžã®ã¢ãããŒã
解æã¯ãäžèšã®ã¢ã³ã±ãŒããªã©ã®ãœãŒã¹èšèªã®ããã¹ããåãå
¥ããç¹å®ã®è¡šçŸã«å€æããããã»ã¹ã§ããéåžžã¯ãããã°ã©ã ã§äœ¿çšã§ããäœããã®ãªããžã§ã¯ãã¢ãã«ã«å€æããŸãã CïŒããã°ã©ããŒã«ã¯ããããå®çŸããæ¹æ³ãããã€ããããŸãã
ææžãããŒãµãŒ
å€ãã®å ŽåãæãåçŽãªããŒãµãŒãšæãè€éãªããŒãµãŒã®äž¡æ¹ãæåã§äœæãããŸãã åçŽãªãã®ã¯ã解決çãæãããªå Žåã«èšè¿°ãããŸãïŒããšãã°ããã«ãŒãå
ã§ã³ã³ããæ€çŽ¢ããŠè¡ãåå²ãããïŒã æãè€éãªããŒãµãŒã¯ãããã°ã©ããŒãç°åžžãªã¬ãã«ã®å¶åŸ¡ïŒããšãã°ãCïŒã³ã³ãã€ã©ãŒïŒãå¿
èŠãšããå Žåã«äœæãããŸãã ãã¡ãããããªãããã®åéã®å°é家ã§ããã圌ãäœãããŠããããæ£ç¢ºã«ç¥ã£ãŠããªãéããæåã§äœãã解æããããšã¯éåžžãåªåãã䟡å€ã¯ãããŸããïŒããã¯ééããªãç§ã«ã€ããŠã§ã¯ãããŸããïŒ
æ£èŠè¡šçŸ
ããã¯ãããã¹ããããã¿ãŒã³ãç
§åããã³æœåºãã䟿å©ãªæ¹æ³ã§ãã .NETã«ã¯ãæ£èŠè¡šçŸãå¹ççã«äœ¿çšããããã®çµã¿èŸŒã¿
System.Text.Regexã¯ã©ã¹ãå«ãŸããŠãããããéåžžã解æã¿ã¹ã¯ã«çŽé¢ãããšãã«èæ
®ããæåã®ãªãã·ã§ã³ã§ãã ããªãåçŽãªææ³ã«ãããããããæ£èŠè¡šçŸã¯ããã«èªã¿ã«ãããªããä¿å®ãã«ãããªããŸãã ããã¯ããããæ倧ã®æ¬ ç¹ã§ãã ããã«ãæ£èŠè¡šçŸã解æã§ããªãææ³ãå€ããããŸãïŒãã¹ããèš±å¯ãããã®ããéå§ïŒã
ããŒãµãŒãžã§ãã¬ãŒã¿ãŒ
ããŒãµãŒãžã§ãã¬ãŒã¿ãŒã§ãããèšèªããŒã«ããããã䜿çšãããšã宣èšåœ¢åŒã§ææ³ãæå®ã§ããŸãã ããŒã«ãããã«ã¯ããããžã§ã¯ãã®ãã«ãäžã«æ©èœããããŒã«ãå«ãŸããŠãããææ³ã解æã§ããã¿ãŒã²ããèšèªïŒCïŒãªã©ïŒã®ã¯ã©ã¹ãçæããŸãã ãã®ãããªããŒã«ã䜿çšãããšãäœæ¥ã調æ»ããŠãããžã§ã¯ãã®ã¢ã»ã³ããªããã»ã¹ã«çµ±åããã®ã«æéãããããŸãã å°ããªè§£æã¿ã¹ã¯ã®å Žåãããã¯åé·ãªå ŽåããããŸãããéåžžã«è€éãªå Žåãé«éã®è§£æé床ãå¿
èŠãªå Žåã¯ããã®ãããªããŒã«ãåŠç¿ããŠäœ¿çšããããšã匷ããå§ãããŸãã
ããŒãµãŒã³ã³ãããŒã¿ãŒ
ãã®é¢æ°ããŒã¹ã®ææ³ã¯ãHaskellãFïŒãªã©ã®é¢æ°åèšèªã§ããã©ã«ãã§äœ¿çšãããããšãå€ããã©ã¡ããé«å質ã®ããŒãµãŒã³ã³ãããŒã¿ãŒã©ã€ãã©ãªãåããŠããŸãã CïŒã«ã¯ãè¬èãªäœ¿çšäººã«ãã£ãŠéçºããããã®èšäºã®åŸåã§äœ¿çšãããè¥ã
Spracheã³ã³ããããªã¢ã«ã©ã€ãã©ãªããããŸãã Spracheã䜿çšãããšãæ¥ãªåŠç¿æ²ç·ãã¢ã»ã³ããªããã»ã¹ãžã®çµ±åãªãã«ãåçŽãªããŒãµãŒãéåžžã«ç°¡åã«èšè¿°ããã³ä¿å®ã§ããŸãã ãã¹ããéããŠéçºããã»ã¹ã«é©ããŠããŸãã çŸåšã®åŒ±ç¹ã«ã¯ãããã©ãŒãã³ã¹ãšãå Žåã«ãã£ãŠã¯ãšã©ãŒã¡ãã»ãŒãžã®å質ãå«ãŸããŸããå°ããªDSLã解æããäžã§å€§ããªåé¡ã¯ãããŸããã [
æŽæ°ïŒãã®èšäºã®å·çåŸãSpracheã®è§£æé床ãšãšã©ãŒåŠçã倧å¹
ã«æ¹åãããŸããã ]
ã¯ããã«
éå§ããã«ã¯ã
Sprache.dllãããŠã³ããŒãããŠãã ãã ã ãã®èšäºã¯ãVisual Studioã§
NUnitã䜿çšããŠããŒãµãŒãäœæããã³ãã¹ãããããã¹ãã远跡ã§ããããã«æ§æãããŠã
ãŸã ã
ææ³ã¯äžããäžã«æ§ç¯ãããŸãã ããŒãµãŒã¯ãèå¥åãæååãæ°å€ãªã©ã®äœã¬ãã«ã®æ§æèŠçŽ çšã«æåã«äœæãããŸãã ãã®åŸããããã®åçŽãªéšåãããè€éãªéšåã«çµåããå®å
šãªèšèªãåŸããããŸã§ãåŸã
ã«é«ããªããŸãã
ID解æ
ãããã¡ã€ã«ãèšè¿°ããããã®èšèªã§ã¯ãæããã¹ããããéèŠãªèŠçŽ ã¯è³ªåã§ãã
name "Full Name"
ããã§ã®äž»èŠãªéšåã¯ãèå¥åãšåŒçšç¬Šã§å²ãŸããããã¹ãã§ãã ããŒãµãŒã®æåã®ã¿ã¹ã¯ã¯ãèå¥åããã®å Žåã¯ãååãã®è§£æã§ãã
[Test] public void AnIdentifierIsASequenceOfCharacters() { var input = "name"; var id = QuestionnaireGrammar.Identifier.Parse(input); Assert.AreEqual("name", id); }
SpracheããŒãµãŒã¯ãææ³ãè¡šãéçã¯ã©ã¹ã¡ãœããã§ãã ã¿ã€ã
Parser <string>ã® QuestionnaireGrammar.Identifier ãã€ãŸã
stringåã®å€ãè¿ããŸãã
ããŒãµãŒå®çŸ©ïŒ
public static readonly Parser<string> Identifier = Parse.Letter.AtLeastOnce().Text().Token();
ãã®ã³ãŒãã¯ããªãèªã¿ãããã§ãã空ã§ãªãæååãåæããããã¹ãè¡šçŸãè¿ããŸãã ããŒãµãŒã®èŠçŽ ã¯æ¬¡ã®ãšããã§ãã
Parse.Letter -Sparcheã®Parseã¯ã©ã¹ã«ã¯ãäžè¬çãªè§£æã¿ã¹ã¯ãå®è¡ããããã®ãã«ããŒã¡ãœãããšããããã£ãå«ãŸããŠããŸãã Letterã¯ãå
¥åããæåãèªã¿åããããã
charãšããŠè¿ãåçŽãª
ããŒãµãŒ<char>ããŒãµãŒã§ãã å
¥åã·ã³ãã«ãæåã§ãªãå Žåããã®ããŒãµãŒã¯ããã«äžèŽããŸããã
AtLeastOnceïŒïŒ -Spracheã䜿çšããŠäœæããããã¹ãŠã®ããŒãµãŒã¯ç¹°ãè¿ãããµããŒãããŸãã AtLeastOnceïŒïŒã¯ã
Tåã®1ã€ã®èŠçŽ ã®ããŒãµãŒãåãåãããã®ãããªèŠçŽ ã®ã·ãŒã±ã³ã¹ã解æããæ°ããããŒãµãŒãè¿ãã
IEnumerable <T>ãè¿ããŸãã
TextïŒïŒ -AtLeastOnceïŒïŒä¿®é£Ÿåã¯
Parser <char>ãååŸãã
Parser <IEnumerable <char >>åã®
ããŒãµãŒã«å€æã
ãŸã ã è£å©é¢æ°
TextïŒïŒã¯ã
Parser <IEnumerable <char >>åã®
ããŒãµãŒãåãåããããã
Parser <string>ã«å€æããŠããã䟿å©ãªäœæ¥ã«ããŸãã
ããŒã¯ã³ïŒïŒã¯ãå
é ããã³æ«å°Ÿã®ç©ºçœãåãå
¥ããŠç Žæ£ãã修食åã§ãã
ãã ïŒ
èå¥åããŒãµãŒã«ã¯ãããã«èå³æ·±ããã¹ããããã€ããããŸãã
[Test] public void AnIdentifierDoesNotIncludeSpace() { var input = "a b"; var parsed = QuestionnaireGrammar.Identifier.Parse(input); Assert.AreEqual(âaâ, parsed); }
Spracheã®åããŒãµãŒã¯ãå¯èœãªéãå€ãã®å
¥åã解æããŸãã ãã®ãã¹ãã§ã¯ã解æã¯æåããŸãããå
¥åæååå
šäœãåžåããŸããã ïŒåŸã§å
¥åã®çµäºãèŠæ±ããæ¹æ³ã確èªããŸããïŒ
[Test] public void AnIdentifierCannotStartWithQuote() { var input = "\"name"; Assert.Throws<ParseException>(() => QuestionnaireGrammar.Identifier.Parse(input)); }
ParseïŒïŒæ¡åŒµã¡ãœããã¯ãããŒãµãŒãé©åã§ãªãå Žåã
ParseExceptionãã¹ããŒããŸãã ãŸããéã¹ããŒã®
TryParseïŒïŒã䜿çšããããšãã§ããŸãã
æ£ãã解æãããèå¥åã«æºè¶³ãããã次ã«é²ã¿ãŸãã
åŒçšããã¹ãã®è§£æ
åŒçšããã¹ãã®è§£æã¯ãèå¥åã®è§£æãããã¯ããã«é£ãããããŸãã-åçŽãªããŒãžã§ã³ã§ã¯ããšã¹ã±ãŒãæåãè€éãªãã®ã¯ãµããŒããããŠããŸããã
å
¥åè¡ãããäžåºŠèŠãŠã¿ãŸãããã
name "Full Name"
åŒçšç¬Šã§å²ãŸããããã¹ãã解æããã«ã¯ãäžèŽããå¿
èŠããããŸãïŒ
- åŒçšç¬Šãéã
- ä»ã®åŒçšç¬Šãé€ããã¹ãŠ
- åŒçšç¬Šãéãã
åŒçšèªäœã¯ç¹ã«èå³æ·±ããã®ã§ã¯ãªããããåŒçšã®éã§ã®ã¿ããã¹ããè¿ããŸãã
ããŒãµãŒã®ãã¹ãã¯æ¬¡ã®ããã«ãªããŸãã
[Test] public void QuotedTextReturnsAValueBetweenQuotes() { var input = "\"this is text\""; var content = QuestionnaireGrammar.QuotedText.Parse(input); Assert.AreEqual("this is text", content); }
ã¢ãã©ã€ã¶ãŒã«çŽè¡ããŸãããã
public static readonly Parser<string> QuotedText = (from open in Parse.Char('"') from content in Parse.CharExcept('"').Many().Text() from close in Parse.Char('"') select content).Token();
LINQã¯ãšãªæ§æã®ãã®äŸ¿å©ãªåå©çšã¯ãFïŒããŒã ã®
Luke Hobanã«ãã£ãŠïŒç§ã®ç¥ãéãïŒæåã«èª¬æãããŸããã æäœããåã
ã®æ§æåäœãåå²ããselectã䜿çšããŠããŒãµãŒå
šäœã®æ»ãå€ã«å€æããŸãã
ããŒã·ã 質å
ããŒãµãŒã匷ãåä»ããããŠããããšã«æ°ã¥ãããããããŸããã
æåã®ããŒãµãŒã¯
charãè¿ããããã¹ãã®ããŒãµãŒã¯
stringãè¿ã
ãŸã ã 質åã®ããŒãµãŒã¯
Questionãè¿ããŸãïŒ
public class Question { public Question(string id, string prompt) { Id = id; Prompt = prompt; } public string Id { get; private set; } public string Prompt { get; private set; } }
ããã¯ãçµã¿åããåæã®å€§ããªå©ç¹ã§ãã åé¡ã®
ã»ãã³ãã£ãã¯ã¢ãã«ãæ§ç¯ããããšããã«ãããŒãµãŒã¯å
¥åããŒã¿ãçŽæ¥å€æã§ããŸãã
public static readonly Parser<Question> Question = from id in Identifier from prompt in QuotedText select new Question(id, prompt);
質åã®åäœãã¹ãã«åæ ŒããŸããïŒ
[Test] public void AQuestionIsAnIdentifierFollowedByAPrompt() { var input = "name \"Full Name\""; var question = QuestionnaireGrammar.Parse(input); Assert.AreEqual("name", question.Id); Assert.AreEqual("Full Name", question.Prompt); }
ã»ã¯ã·ã§ã³è§£æ
ã»ã¯ã·ã§ã³ã®åæã¯ã質åã®åæãšåãã§ããæåã«ã»ãã³ãã£ãã¯ã¢ãã«ãæ§ç¯ãã次ã«æ¢åã®ããŒãµãŒã䜿çšããŠããœãŒã¹ããã¹ããããã«å€æããŸãã
ãã®ã»ã¯ã·ã§ã³ã¯æ¬¡ã®ããã«ãªããŸãã
identification "Personal Details" [ name "Full Name" department "Department" ]
次ã®ããã«ãªããžã§ã¯ãã¢ãã«ã§è¡šçŸã§ããŸãã
public class Section { public Section(string id, string title, IEnumerable<Question> questions) { Id = id; Title = title; Questions = questions; } public string Id { get; private set; } public string Prompt { get; private set; } public IEnumerable<Question> Questions { get; private set; } }
ããŒãµãŒã®éçºã¯ããªããžã§ã¯ãã¢ãã«ã®éçºãšåããããç°¡åã§ãã
public static readonly Parser<Section> Section = from id in Identifier from title in QuotedText from lbracket in Parse.Char('[').Token() from questions in Question.Many() from rbracket in Parse.Char(']').Token() select new Section(id, title, questions);
ãã®äŸãå®äºããããã«ãå¥ã®ã¢ãã«ã¯ã©ã¹ããããŸãã
public class Questionnaire { public Questionnaire(IEnumerable<Section> sections) { Sections = sections; } public IEnumerable<Section> Sections { get; private set; } }
察å¿ããããŒãµãŒïŒä»åã¯æ§æã解æããã«ïŒïŒ
public static Parser<Questionnaire> Questionnaire = Section.Many().Select(sections => new Questionnaire(sections)).End();
.EndïŒïŒä¿®é£Ÿåã§ã¯ããã¹ãŠã®å
¥åããŒã¿ã解æããå¿
èŠããããŸãïŒã€ãŸããæåŸã«ãŽããæ®ã£ãŠããŸããïŒã
ããã¯ãããŒã¿å修食åãªãã®äŸã«å¿
èŠãªãã¹ãŠã§ãã
å¿çããŒã¿åã®ãµããŒã
ææ³ã®æåŸã®ä»äžãã¯ãåçã¿ã€ã修食åã®ãµããŒãã§ãã
#months "Total Months Employed"
ããããè¡šãããã«ãå¯èœãªãã¹ãŠã®åã®åæã䜿çšã§ããŸãã
public enum AnswerType { Natural, Number, Date, YesNo }
ããã¯ããªãéãããã»ãããªã®ã§ãåæã䜿çšããŠãå¯èœãªãã¹ãŠã®ä¿®é£Ÿåããã§ãã¯ããŸãã
public static Parser<AnswerType> AnswerTypeIndicator = Parse.Char('#').Return(AnswerType.Natural) .Or(Parse.Char('$').Return(AnswerType.Number)) .Or(Parse.Char('%').Return(AnswerType.Date)) .Or(Parse.Char('?').Return(AnswerType.YesNo));
Questionã¯ã©ã¹ã¯ã
AnswerTypeãã³ã³ã¹ãã©ã¯ã¿ãŒãã©ã¡ãŒã¿ãŒãšããŠåãå
¥ããããã«å€æŽãããŸããã 質åããŒãµãŒã®ç°¡åãªå€æŽã§äœæ¥ãå®äºããŸãã
public static Parser<Question> Question = from at in AnswerTypeIndicator.Or(Parse.Return(AnswerType.Text)) from id in Identifier from prompt in QuotedText select new Question(id, prompt, at);
ãŸãšã
å®å
šãªã¢ãã©ã€ã¶ãŒã¯ã25ã®æŽåœ¢åŒã®ã³ãŒãè¡ã«ãã6ã€ã®ã«ãŒã«ã§ãã
ä¿¡é Œã§ããæ§æ解æã¯çŸå®ã®äžçã§ã¯äºçŽ°ãªäœæ¥ã§ã¯ãããŸãããããã®èšäºã§æ£èŠè¡šçŸãšèšèªããŒã«ã®ã®ã£ãããåããç°¡åãªããªãšãŒã·ã§ã³ãããããšã瀺ããããšæããŸãã