å人ã®æšæ¶ã ä»æ¥ã¯ãCïŒã§ã®ãããã³ã°ã®å®è£
ãšãAMFããŒã¿ããµãŒããŒã«éä¿¡ããäŸã䜿çšããŠå®éã®åé¡ã解決ããéã®ãã®å®è£
ã®é©çšã«ã€ããŠèª¬æããŸãã 以äžã®ãã¹ãŠã¯ãã¢ã«ãŽãªãºã ã®å®è£
ããã³ã³ãŒãèšèšã®ãã¿ãŒã³ã®æšæºãè£
ããã®ã§ã¯ãããŸãããããã¯ãåå¿è
ã«ã¯åžžã«æããã§ã¯ãªãå€ãã®ãœãªã¥ãŒã·ã§ã³ã®1ã€ã®èª¬æã«ãããŸããã
ãã®èšäºãåŠç¿ããéçšã§ãç¬èªã®
å±æ§ãå®è£
ããããããé©çšãã
æ¹æ³ãåŠã³ãå®é
ã«åæ¡åŒµã®
æ¹æ³ãš
ãªãã¬ã¯ã·ã§ã³ã®é©çšã«ç²Ÿéãã
MSILã®
åºæ¬ ãç¹ã«
OpCodeã® åºæ¬ãããã³
AMFã§ãªããžã§ã¯ãã
ã·ãªã¢ã«åããæ¹æ³ãåŠã³
ãŸãã¹ã¬ããã䜿çšããŸãã
åé¡ã®å£°æ
ãŸãããã®èšäºã§è§£æ±ºããå¿
èŠãããã¿ã¹ã¯ã®ããããã®ãªã¹ããäœæããŸãããã 次ã®ããã«ããŸãã
- ä»»æã®ã¿ã€ãã®ãµãŒããŒããŒã¿ãCïŒã³ãŒãã§èšè¿°ãããããã䟿å©ã«æäœããæ©èœã
- ä»»æã®ã¿ã€ãã®ã·ãªã¢ã«å/éã·ãªã¢ã«åã®å¯èœæ§ïŒç§ãã¡ã説æãããã®ãšããã§ãªããã®ã®äž¡æ¹ïŒ;
- ãµãŒããŒèªäœã«ããŒã¿ãéä¿¡ããã¡ã«ããºã ã
ãã®èšäºã®ãã¬ãŒã ã¯ãŒã¯ã§ã¯ãäœããã®æ¢è£œã®æœè±¡ãµãŒããŒã䜿çšããŸãïŒãŠãŒã¶ãŒã®å Žåãããã¯éåžžã«å®éã«æ©èœãããµãŒããŒã§ããããŠãŒã¶ãŒã®åå ãªãã«å®è£
ãããŸãïŒã ãµãŒããŒåŽãFlexã§èšè¿°ãããŠããããšãããã£ãŠãããšä»®å®ãããšãAMFãªããžã§ã¯ããéä¿¡ããå¿
èŠãããçŽæ¥ãªã³ã¯ãæ¢ã«åä¿¡ããŠããŸãã AMFèªäœãçŽæ¥æäœããããã«ããµãŒããŒåŽãšã¯ã©ã€ã¢ã³ãåŽã®äž¡æ¹ã§FlexãµããŒããæŽçããããã«å¿
èŠãªãã¹ãŠã®ããŒã«ãæäŸããçŽ æŽããã
FluorineFXãã¬ãŒã ã¯ãŒã¯ããããŸãã ããããåé¡ã¯ããªããžã§ã¯ãããµãŒããŒã«éä¿¡ããéåžžã«åŸ
ãããç¬éã«ãªããšãFluorineFXããããã³ã°ã®ããã®äŸ¿å©ãªæ段ãæäŸããããµãŒããŒã«éä¿¡ããããã¹ãŠã®ãªããžã§ã¯ããå
ã®ã¿ã€ãã¡ã¿ããŒã¿ã§é£è¡ããããšã§ãã å®éãã¯ã©ã€ã¢ã³ãåŽãšãµãŒããŒåŽã®äœæè
ã§ããã°ãããã¯ãŸã£ããåé¡ã§ã¯ãããŸããããã«ã¹ã¿ã æ§é ãæã€ããŒã¿ãã±ãããéä¿¡ããå¿
èŠãããå Žåã¯ã©ãã§ããããã 1 in 1åå空éãšååãç¹°ãè¿ãããšã¯å¿
ããã䟿å©ã§ã¯ãããŸããïŒæã«ã¯äžå¯èœãªå ŽåããããŸãïŒã å°ãã°ãŒã°ã«ã§ãè¿ãã§å®å
šã«æ©èœãã
ãœãªã¥ãŒã·ã§ã³ãèŠã€ããŸãã ãã®äž»ãªé·æãšçæãããã«æ€èšããŠãã ããã
é·æïŒ
- ã¹ããŒãã FluorineFXã®ãœãŒã¹ã³ãŒããçŽæ¥å€æŽããåéããŠã楜ãã¿ãã ããã
çæïŒ
- ãµããŒãã ããŒã ã§äœæ¥ããå ŽåãããŒã éçºã®ãã¹ãŠã®åå è
ããœãŒã¹FluorineFXãåžžã«å©çšã§ããããã«ããåžžã«é¢é£æ§ãç¶æããå¿
èŠããããŸãã ããã«ã¯ãããå€ãã®ãããžã§ã¯ãã³ãŒããå¿
èŠã§ããããããµããŒãã«æéãããããŸãã
- æŽæ°ã FluorineFXã®æ°ããããŒãžã§ã³ããªãªãŒã¹ãããå Žåãæ倧éã®äºææ§ãç¶æããªããããœãŒã¹ã³ãŒãå
šäœãåæŽæ°ããŠå€æŽããå¿
èŠããããŸããããã¯éåžžã«äžäŸ¿ã§ãã ããã§ããããããå¯äžã®ãã©ã¹ã®ãã€ã³ãã¯ãæŽæ°ããåžžã«æ°ããæ©èœãå¿
èŠã«ãªãå¯èœæ§ãããããã¬ãŒã ã¯ãŒã¯èªäœããã£ãã«æŽæ°ãããªãããšã§ãã ããããæé©ãªã¯ãŒã¯ãããŒïŒããã³å¥ã®åé¡ã解決ãããšãã«åæ§ã®ç¶æ³ãçºçããå¯èœæ§ãããå ŽåïŒã®å Žåããã®ç¹ã¯éåžžã«éèŠã§ãã
ãã®æ±ºå®ã®äžå©çã«æ¥ãããããªã人ã®ããã«ã以äžã®ãã¹ãŠã®è³æã¯å¿
èŠã§ã¯ãªããããããŸããã ç§ãšäžç·ã«åã£ãŠããæè»ãªãœãªã¥ãŒã·ã§ã³ãèŠã€ããããšã«ãã人ã«ãšã£ãŠã以äžã®è³æã¯éåžžã«èå³æ·±ããã®ã«ãªããŸãã
å±æ§ãæäœãã
äžè¬ã«ã
ãœãªã¥ãŒã·ã§ã³ã§èª¬æãããŠããã¢ãããŒãã¯æ£ããæ¹åã«é²ã¿ãŸãã ãããã³ã°èªäœã¯ãã¿ã€ãã¡ã¿ããŒã¿ã®ã¬ãã«ã§ã®ããçš®ã®ãã€ã³ãã£ã³ã°ãæå³ããŸããããã«ã¯å±æ§ãå¿
èŠã§ãã
ãŸããAMFã§ã®ã·ãªã¢ã«åã®ããã«åãæºåãããšãã«ãåãã©ã®ããã«èŠãããã«ã€ããŠå€§ãŸããªèª¬æãæžããŸãããã 次ã®æ©èœãæäŸããŸãã
- å±æ§ãæå®ãããŠããåã¯ãå±æ§ããããã£ã§æå®ãããååã§ã·ãªã¢ã«åãããŸãã
- å±æ§ãæå®ãããŠããªãåïŒãŸãã¯ããããã£ãnullã§ããå±æ§ïŒã¯ãå
ã®ã¢ã»ã³ããªã§å®çŸ©ãããåã®å
ã®ååã§ã·ãªã¢ã«åãããŸãã
- å±æ§ãèšå®ãããŠããããããã£ããã³ã¿ã€ããã£ãŒã«ãã¯ãå±æ§ããããã£ã§æå®ãããååã§ã·ãªã¢ã«åãããŸãã
- å±æ§ãèšå®ãããŠãããå±æ§ããããã£ãnullã§ããããããã£ãšåãã£ãŒã«ãã¯ãå
ã®ã¢ã»ã³ããªã§å®çŸ©ãããå
ã®ååã§ã·ãªã¢ã«åãããŸãã
- å±æ§ãæå®ãããŠããªãããããã£ããã³åãã£ãŒã«ãã¯ãã·ãªã¢ã«åããã»ã¹ã«åå ãããæçµåã®ã¡ã³ããŒã®äžéšã§ã¯ãããŸããã
- èŸæžã¯ãAMFé£æ³é
åãšããŠã·ãªã¢ã«åããå¿
èŠããããŸãã
- é
ååã¯ãã¹ãŠãAMFãªããžã§ã¯ãã®é
åãšããŠã·ãªã¢ã«åããå¿
èŠããããŸãã
- çµã¿èŸŒã¿åã¯ãAMFãªããžã§ã¯ãã®çµã¿èŸŒã¿åãšããŠã·ãªã¢ã«åããå¿
èŠããããŸãã
å±æ§ã¯ã©ã¹ãå®è£
ããããšããå§ããŸãããã ãªããžã§ã¯ãã¿ã€ããšãã£ãŒã«ãã¿ã€ããšãªããžã§ã¯ãããããã£ã«åäžã®å±æ§ãæžã蟌ãããšãã§ããŸãïŒ
ãœãªã¥ãŒã·ã§ã³ãšåæ§ïŒããã¿ã€ããšã¿ã€ãã¡ã³ããŒã«åå¥ã®å±æ§ãå®è£
ããããšããå§ãããŸããããã¯ãç°ãªãã€ã³ã¹ã¿ã³ã¹ã®ã¿ã€ãããã¡ã¿ããŒã¿ãåŠçããããžãã¯ãåé¢ããå¿
èŠããããšãã«äŸ¿å©ã§ãã ãŸãããªããžã§ã¯ãã¿ã€ãã®å±æ§ã¯ã©ã¹ãå®è£
ããŸãã
/// <summary> /// AMF. /// </summary> [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)] public class AmfObjectAttribute : Attribute { /// <summary> /// . /// </summary> public string Name { get; set; } /// <summary> /// <see cref="AmfObjectAttribute"/>. /// </summary> /// <param name="name"> .</param> public AmfObjectAttribute(string name) { Name = name; } /// <summary> /// <see cref="AmfObjectAttribute"/>. /// </summary> public AmfObjectAttribute() : this(null) { } }
å±æ§ã®å®è£
ã«ãããããã€ãã®éèŠãªãã€ã³ãïŒ
- ãã¹ãŠã®å±æ§ã¯System.Attributeã¯ã©ã¹ããç¶æ¿ããå¿
èŠããããŸãã
- AttributeUsageAttribute å±æ§ã¯ ãå±æ§ã®ã¹ã³ãŒãã決å®ããããã«å¿
èŠã§ãã ãã®å©ãã«ãããå®è£
ãããå±æ§ãé©çšãããã¡ã¿ããŒã¿ã®ã¿ã€ããèšå®ããã³é€å€ããããšãã§ããŸãã
- ããã©ã«ãã®ã³ã³ã¹ãã©ã¯ã¿ãŒãæå®ããªãå Žåããã©ã¡ãŒã¿ãŒãæã€ãªãŒããŒããŒããããã³ã³ã¹ãã©ã¯ã¿ãŒãä»ããŠã®ã¿ãåæåæã«æ瀺çã«å±æ§ããããã£ã«å€ãå²ãåœãŠãããšãã§ããŸããã
- å±æ§ã¿ã€ããæå®ããå Žåããµãã£ãã¯ã¹... Attributeã¯çç¥ã§ããŸãã
AmfObjectAttributeå±æ§ã¯ããªããžã§ã¯ãã¿ã€ãã«é©çšãããŸãã ãã®å±æ§ã䜿çšãããšãã·ãªã¢ã«åããããªããžã§ã¯ãã®
ååã¯
AmfObjectAttributeããããã£ã§æå®ãããå€ãšäžèŽããŸã
ã Name ãããããã£å€ãnullã®å Žåãã·ãªã¢ã«åããããªããžã§ã¯ãã¯å
ã®ååãä¿æããŸãã ãã®å±æ§ã§ããŒã¯ãããŠããªãåã®ãªããžã§ã¯ããã·ãªã¢ã«åããå¯ââèœæ§ãå®çŸããããã«ãæå³çã«åã®å±æ§ã®ååšã確èªããŸããã§ããã
次ã«ãã¿ã€ãã®ããããã£ãšãã£ãŒã«ãã®å±æ§ã¯ã©ã¹ãå®è£
ããŸãã
/// <summary> /// AMF. /// </summary> [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)] public class AmfMemberAttribute : Attribute { /// <summary> /// . /// </summary> public string Name { get; set; } /// <summary> /// <see cref="AmfMemberAttribute"/>. /// </summary> /// <param name="name"> .</param> public AmfMemberAttribute(string name) { Name = name; } /// <summary> /// <see cref="AmfMemberAttribute"/>. /// </summary> public AmfMemberAttribute() : this(null) { } }
å±æ§ã®å®è£
ãç解ããã®ã§ãç¹å®ã®ããŒã¿ã¢ãã«ãèšè¿°ããåçŽãªã¯ã©ã¹ãäœæããŸãããã å°æ¥çã«ã¯ããã¹ãã«äœ¿çšããŸãã
/// <summary> /// AMF- . "namespase.of.your.object". /// </summary> [AmfObject("namespase.of.your.object")] public class CustomAmfObject { /// <summary> /// <see cref="bool"/>. "bit_prop". /// </summary> [AmfMember("bit_prop")] public bool BooleanProperty { get; set; } = true; /// <summary> /// <see cref="sbyte"/>. UnsignedByteProperty. /// </summary> [AmfMember] public sbyte UnsignedByteProperty { get; set; } = 2; /// <summary> /// <see cref="string"/>. . /// </summary> public string StringProperty { get; set; } = "test"; /// <summary> /// <see cref="bool"/>. "bit_fld". /// </summary> [AmfMember("bit_fld")] public bool booleanField = false; /// <summary> /// <see cref="float"/>. singleField. /// </summary> [AmfMember] public float singleField = -5.00065f; /// <summary> /// <see cref="string"/>. . /// </summary> public string stringField = "test2"; /// <summary> /// <see cref="CustomAmfObject"/>. /// </summary> public CustomAmfObject() { } }
å±æ§ãæžã蟌ãŸãããã¹ãã¯ã©ã¹ãå®è£
ãããŸãã ããã§ãã·ãªã¢ã«åèªäœã®åé¡ã®è§£æ±ºãéå§ããå¿
èŠããããŸãã .NET 2.0ã®ãµããŒããèšç»ããŠããå Žåã¯ããªããžã§ã¯ãã€ã³ã¹ã¿ã³ã¹ã§åäœãããã®ã¿ã€ãã®ã¡ã¿ããŒã¿ã§ããŸããŸãªæäœãå®è¡ããã·ãªã¢ã©ã€ã¶ãŒã¯ã©ã¹ãå®è£
ããå¿
èŠããããŸãã CïŒ-engineerã®2ã€ã®éåžžã«éèŠãªæ©èœãç»å ŽãããããããŒãžã§ã³.NET 3.5ã®ãµããŒããèæ
®ããŠã³ãŒããèšè¿°ããŸãïŒLINQãšåæ¡åŒµã¡ãœããã åé¡ã解決ããããã«ããããé©çšããŸãã
æ¡åŒµã¡ãœãããšãªãã¬ã¯ã·ã§ã³
åæ¡åŒµã¡ãœãããå®è£
ããã«ã¯ããããªãã¯éçã¯ã©ã¹ã宣èšããthis修食åãæåã®ãã©ã¡ãŒã¿ãŒã«è¿œå ããã ãã§ååã§ãã ãããã®æ¡ä»¶ã¯å¿
é ã§ãããã以å€ã®å Žåãã³ã³ãã€ã©ã¯ã¡ãœãããåã®æ¡åŒµã§ããããšãåã«ç解ããŸããã å®è£
åŸããã®ã¡ãœããã¯ãåãã¿ã€ãã®ãªããžã§ã¯ãããŸãã¯æ¡åŒµã¡ãœããã®æåã®ãã©ã¡ãŒã¿ãŒã®ã¿ã€ãããç¶æ¿ããããªããžã§ã¯ãã«é©çšã§ããŸãã æ¡åŒµã¡ãœããã®ç¬èªã®ã¯ã©ã¹ãäœæããŸãããïŒ
/// <summary> /// / AMF. /// </summary> public static class Extensions { }
ãŸããã³ãŒããåå©çšããããã«ããã€ãã®ãã«ããŒã¡ãœãããå¿
èŠã«ãªããŸãã .NET 4.5ã§ã¯ã
Attribute Type .GetCustomAttributeïŒ Type ïŒã¡ãœãããå°å
¥ãããŸãããããã«ãããæå®ããã¿ã€ãã®å±æ§ãããã«ååŸã§ããŸãã .NET 3.5ã§ã¯ãããã¯ãŸã ã§ã¯ãªãã®ã§ãå±æ§ã䜿çšããŠäŸ¿å©ã«äœæ¥ããããã®æ¡åŒµã¡ãœãããããã€ãå®è£
ããŸãã
/// <summary> /// . /// </summary> /// <typeparam name="T"> .</typeparam> /// <param name="sourceType"> .</param> /// <returns></returns> private static T GetAttribute<T>(this Type sourceType) where T : Attribute { object[] attributes = sourceType.GetCustomAttributes(typeof(T), true); // . if (attributes == null || attributes.Length == 0) return default(T); // - null. return attributes[0] as T; } /// <summary> /// . /// </summary> /// <typeparam name="T"> .</typeparam> /// <param name="sourceMember"> .</param> /// <returns></returns> private static T GetAttribute<T>(this MemberInfo sourceMember) where T : Attribute { object[] attributes = sourceMember.GetCustomAttributes(typeof(T), true); // . if (attributes == null || attributes.Length == 0) return default(T); // - null. return attributes[0] as T; } /// <summary> /// , . /// </summary> /// <typeparam name="T"> .</typeparam> /// <param name="sourceType"> .</param> /// <returns></returns> private static bool IsDefinedAttribute<T>(this Type sourceType) { object[] attributes = sourceType.GetCustomAttributes(typeof(T), true); // . return attributes != null && attributes.Length > 0; }
åã·ãªã¢ã«åæé ã§ã¯ãæå®ãããå±æ§ã«ãã£ãŠåãçæãããŸãã ã·ãªã¢ã«åã¡ãœããã®åŒã³åºãããšã«å€ãã®æäœãç¹°ãè¿ããªãããã«ãäœæåŸã«åçã¢ã»ã³ããªã«ã¡ã¿ããŒã¿ãæ ŒçŽããå¯èœæ§ãããã«èããŠã¿ãŸãããã
/// <summary> /// . /// </summary> private static ModuleBuilder moduleBuilder; /// <summary> /// <see cref="Extensions"/>. /// </summary> static Extensions() { AssemblyName assemblyName = new AssemblyName("AmfDynamicAssembly"); // . AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave); // . moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name, assemblyName.Name + ".dll"); // . }
ããã§ããã¹ãŠã®ã¿ã€ãã«ã€ããŠãç¬èªã®åäžã®åçã¢ã»ã³ããªãäœæãããã¡ã¿ããŒã¿ãä¿åãããŸãã å±æ§ã®ããŒã¿ã«åºã¥ããŠåçæã¢ã«ãŽãªãºã ãå®è£
ãããšããæ¥ãŸããã æåã«ãã¢ã«ãŽãªãºã ã®åã¹ããããã¹ãããããšã«å®è¡ããŠãããã¡ãœããã®å®å
šãªãªã¹ããæäŸããŸãã
ããªãã¬ã¯ã·ã§ã³ãïŒããªãã¬ã¯ã·ã§ã³ãã§ããããããªãã¬ã¯ã·ã§ã³ãã§ãããïŒã®æŠå¿µã¯ãã¿ã€ãã®ã¡ã¿ããŒã¿ã䜿çšããæäœã«åºã¥ããŠããŸãã å®éãããã§ã¯ãã¹ãŠãã·ã³ãã«ã§ãã ã³ã³ãã€ã©ã«ãã£ãŠã³ãŒãã«èšè¿°ãããåãäœæããããã»ã¹ãç¹°ãè¿ãå¿
èŠããããŸãããç¬èªã®ã³ãŒãã䜿çšããŸãã åºç€ãšããŠãæ¢ç¥ã®ãœãŒã¹ãªããžã§ã¯ãã®ã¿ã€ãã®ã¡ã¿ããŒã¿ãšãããããã°å±æ§ããã®ããŒã¿ãååŸããŸãã ãŸããçæãããåã®ãªããžã§ã¯ãã®ã€ã³ã¹ã¿ã³ã¹ãžã®åç
§ãåæåããããã©ã«ãã®ã³ã³ã¹ãã©ã¯ã¿ãå®è£
ããå¿
èŠããããŸãã
ModuleBuilder.TypeBuilderã¯ã©ã¹ã䜿çšããŠãå¿
èŠãªãã¹ãŠã®æäœãå®è¡ã§ããŸãã
TypeBuilderã䜿çšããŠã¿ã€ãã決å®ã
ãŸã ã
TypeBuilder typeBuilder = moduleBuilder.DefineType(typeName, TypeAttributes.Public);
FieldBuilderã䜿çšããŠãã£ãŒã«ããå®çŸ©ããïŒ
FieldBuilder fieldBuilder = typeBuilder.DefineField($"m_{propertyName}", propertyType, FieldAttributes.Private);
PropertyBuilderã䜿çšããŠããããã£ãå®çŸ©ããŸãã ããã§ã¯ããã©ã€ããŒããã£ãŒã«ããšãããã«ã¢ã¯ã»ã¹ããããã®ã¢ã¯ã»ãµãŒãšãã¥ãŒããŒã¿ãŒãå®çŸ©ããå¿
èŠããããŸãã
PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, null); // . MethodAttributes getSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig; // . MethodBuilder methodBuilderAccessor = typeBuilder.DefineMethod($"get_{propertyName}", getSetAttr, propertyType, Type.EmptyTypes); // . ILGenerator accessorIL = methodBuilderAccessor.GetILGenerator(); // MSIL- . accessorIL.Emit(OpCodes.Ldarg_0); // . accessorIL.Emit(OpCodes.Ldfld, fieldBuilder); // . accessorIL.Emit(OpCodes.Ret); // . MethodBuilder methodBuilderSetter = typeBuilder.DefineMethod($"set_{propertyName}", getSetAttr, null, new Type[] { propertyType }); // . ILGenerator setterIL = methodBuilderSetter.GetILGenerator(); // MSIL- . setterIL.Emit(OpCodes.Ldarg_0); // . setterIL.Emit(OpCodes.Ldarg_1); // . setterIL.Emit(OpCodes.Stfld, fieldBuilder); // . setterIL.Emit(OpCodes.Ret); // . propertyBuilder.SetGetMethod(methodBuilderAccessor); // . propertyBuilder.SetSetMethod(methodBuilderSetter); // .
ConstructorBuilderã䜿çšããŠããã©ã«ãã³ã³ã¹ãã©ã¯ã¿ãŒãå®çŸ©ããïŒ
ConstructorBuilder ctor = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, Type.EmptyTypes); // . ILGenerator ctorIL = ctor.GetILGenerator(); // MSIL- . ctorIL.Emit(OpCodes.Ldarg_0); // . ctorIL.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes)); // . ctorIL.Emit(OpCodes.Ret); // .
Activatorã䜿çšããŠãçæãããã°ããã®ã¿ã€ãã®ãªããžã§ã¯ãã®æ°ããã€ã³ã¹ã¿ã³ã¹ãåæåããŸãã
object targetObject = Activator.CreateInstance(typeBuilder.CreateType());
ãã¹ãŠã®ã¡ãœããã¡ã¿ããŒã¿ã³ã¬ã¯ã¿ãŒã«ã¯ã
ILGeneratorã€ã³ã¹ã¿ã³ã¹ãè¿ã
GetILGeneratorïŒïŒã¡ãœããããããŸã
ïŒããã«ãããç®çã®ã¹ããŒãã¡ã³ãã®ã·ãŒã±ã³ã¹ãå®è¡ã®ããã«MSILèšç®ã¹ã¿ãã¯ã«é
眮ã§ããŸãïŒã
OpCodesããæž¡ãILåœä»€ã®ã»ããã¯ã説æããã¡ãœããã®ããžãã¯ã®åäœãçŽæ¥æ±ºå®ããŸãã ãã®èšäºã§ã¯ããªãã¬ã¯ã·ã§ã³ã®ãããã¯ã«ã€ããŠè¡šé¢çã«è§ŠããŠããŸãããããã¯æ¢ã«å¥ã®èšäºã®æ©äŒã§ããããã«ãå
¬åŒã®MSDNããã¥ã¡ã³ãã®æ瀺ã®å
šãªã¹ãããã€ã§ãèªãããšãã§ããŸãã
åã¡ã¿ããŒã¿ãåçã«çæããããã®ããžãã¯ãèšè¿°ããããã«å¿
èŠãªãã®ã¯ãã¹ãŠæã£ãŠããŸãã çæãããåã®ããããã£ãšãã£ãŒã«ããã·ãªã¢ã«åå±æ§ãæã€ããšãã§ãããšããäºå®ãããã«èæ
®ããŠãã ãããååž°ã¯å®è£
ã«é©çšã§ããŸãã ãªããžã§ã¯ãã«äžèŽããã¿ã€ãåã®å±æ§ããªãå Žåã¯ããã®ãŸãŸè¿ããŸãã åçã¢ã»ã³ããªã«æ¢ã«ã¿ã€ãã®ã¡ã¿ããŒã¿ãããå Žåããããã«åºã¥ããŠãªããžã§ã¯ãã€ã³ã¹ã¿ã³ã¹ãåéããŸãã ããã¯ãã¹ãŠæé©åã«åœ¹ç«ã¡ãŸãã å¿
èŠãªãã¹ãŠã®ãã§ãã¯ãšæé ãå«ããçææ¹æ³ã®å®å
šãªãªã¹ãã¯æ¬¡ã®ãšããã§ãã
/// <summary> /// <see cref="AmfObjectAttribute"/>, , <see cref="AmfMemberAttribute"/>. /// </summary> /// <param name="sourceObject"> .</param> /// <returns></returns> private static object GenerateType<T>(T sourceObject) { Type sourceType = sourceObject.GetType(); // . if (sourceType.IsDictionary()) return GenerateType(sourceObject as IEnumerable<KeyValuePair<string, object>>); if (!sourceType.IsDefinedAttribute<AmfObjectAttribute>()) return sourceObject; // - . string typeName = sourceType.GetAttribute<AmfObjectAttribute>().Name ?? sourceType.FullName; // . Type definedType = moduleBuilder.GetType(typeName); // . TypeBuilder typeBuilder = null; // . Dictionary<string, object> properties = new Dictionary<string, object>(); // . Dictionary<string, object> fields = new Dictionary<string, object>(); // . // ... if (definedType == null) { typeBuilder = moduleBuilder.DefineType(typeName, TypeAttributes.Public); // . ConstructorBuilder ctor = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, Type.EmptyTypes); // . ILGenerator ctorIL = ctor.GetILGenerator(); // MSIL- . ctorIL.Emit(OpCodes.Ldarg_0); // . ctorIL.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes)); // . ctorIL.Emit(OpCodes.Ret); // . // . foreach (PropertyInfo propertyInfo in sourceType.GetProperties()) { AmfMemberAttribute attribute = propertyInfo.GetAttribute<AmfMemberAttribute>(); // AmfMemberAttribute. if (attribute == null) continue; // - . string propertyName = attribute.Name ?? propertyInfo.Name; // . object propertyValue = propertyInfo.GetValue(sourceObject, null); // . Type propertyType = propertyInfo.PropertyType; // . // ... if (propertyInfo.PropertyType.IsDefinedAttribute<AmfObjectAttribute>() || propertyType.IsDictionary()) { // , . propertyValue = propertyType.IsDictionary() ? GenerateType(propertyValue as IEnumerable<KeyValuePair<string, object>>) : GenerateType(propertyValue); propertyType = propertyValue.GetType(); // . } FieldBuilder fieldBuilder = typeBuilder.DefineField($"m_{propertyName}", propertyType, FieldAttributes.Private); // . PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, null); // . MethodAttributes getSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig; // . MethodBuilder methodBuilderAccessor = typeBuilder.DefineMethod($"get_{propertyName}", getSetAttr, propertyType, Type.EmptyTypes); // . ILGenerator accessorIL = methodBuilderAccessor.GetILGenerator(); // MSIL- . accessorIL.Emit(OpCodes.Ldarg_0); // . accessorIL.Emit(OpCodes.Ldfld, fieldBuilder); // . accessorIL.Emit(OpCodes.Ret); // . MethodBuilder methodBuilderSetter = typeBuilder.DefineMethod($"set_{propertyName}", getSetAttr, null, new Type[] { propertyType }); // . ILGenerator setterIL = methodBuilderSetter.GetILGenerator(); // MSIL- . setterIL.Emit(OpCodes.Ldarg_0); // . setterIL.Emit(OpCodes.Ldarg_1); // . setterIL.Emit(OpCodes.Stfld, fieldBuilder); // . setterIL.Emit(OpCodes.Ret); // . propertyBuilder.SetGetMethod(methodBuilderAccessor); // . propertyBuilder.SetSetMethod(methodBuilderSetter); // . properties.Add(propertyName, propertyValue); // . } // . foreach (FieldInfo fieldInfo in sourceType.GetFields()) { AmfMemberAttribute attribute = fieldInfo.GetAttribute<AmfMemberAttribute>(); // AmfMemberAttribute. if (attribute == null) continue; // - . string fieldName = attribute.Name ?? fieldInfo.Name; // . object fieldValue = fieldInfo.GetValue(sourceObject); // . Type fieldType = fieldInfo.FieldType; // . // ... if (fieldInfo.FieldType.IsDefinedAttribute<AmfObjectAttribute>() || fieldType.IsDictionary()) { // , . fieldValue = fieldType.IsDictionary() ? GenerateType(fieldValue as IEnumerable<KeyValuePair<string, object>>) : GenerateType(fieldValue); fieldType = fieldValue.GetType(); // . } typeBuilder.DefineField(fieldName, fieldType, FieldAttributes.Public); // . fields.Add(fieldName, fieldValue); // . } } else { // . foreach (PropertyInfo propertyInfo in sourceType.GetProperties()) { AmfMemberAttribute attribute = propertyInfo.GetAttribute<AmfMemberAttribute>(); // AmfMemberAttribute. if (attribute == null) continue; // - . string propertyName = attribute.Name ?? propertyInfo.Name; // . object propertyValue = propertyInfo.GetValue(sourceObject, null); // . Type propertyType = propertyInfo.PropertyType; // . AmfObjectAttribute propertyAttribute = propertyInfo.PropertyType.GetAttribute<AmfObjectAttribute>(); // . // ... if (propertyAttribute != null || propertyType.IsDictionary()) { // , . propertyValue = propertyType.IsDictionary() ? GenerateType(propertyValue as IEnumerable<KeyValuePair<string, object>>) : GenerateType(propertyValue); propertyType = propertyValue.GetType(); // . } properties.Add(propertyName, propertyValue); // . } // . foreach (FieldInfo fieldInfo in sourceType.GetFields()) { AmfMemberAttribute attribute = fieldInfo.GetAttribute<AmfMemberAttribute>(); // AmfMemberAttribute. if (attribute == null) continue; // - . string fieldName = attribute.Name ?? fieldInfo.Name; // . object fieldValue = fieldInfo.GetValue(sourceObject); // . Type fieldType = fieldInfo.FieldType; // . AmfObjectAttribute fieldAttribute = fieldInfo.FieldType.GetAttribute<AmfObjectAttribute>(); // . // ... if (fieldAttribute != null || fieldType.IsDictionary()) { // , . fieldValue = fieldType.IsDictionary() ? GenerateType(fieldValue as IEnumerable<KeyValuePair<string, object>>) : GenerateType(fieldValue); fieldType = fieldValue.GetType(); // . } fields.Add(fieldName, fieldValue); // . } } object targetObject = Activator.CreateInstance(definedType ?? typeBuilder.CreateType()); // . // . foreach (KeyValuePair<string, object> property in properties) targetObject.GetType().GetProperty(property.Key).SetValue(targetObject, property.Value, null); // . foreach (KeyValuePair<string, object> field in fields) targetObject.GetType().GetField(field.Key).SetValue(targetObject, field.Value); return targetObject; }
次ã«ãã·ãªã¢ã«åäžã«ãªããžã§ã¯ãã®é
åã®ã¡ã¿ããŒã¿ãæ£ããä¿åãããããšã確èªããå¿
èŠããããŸãã ãããè¡ãã«ã¯ãåçæã¡ãœããã®åºæ¬çãªãªãŒããŒããŒããèšè¿°ããŸãã
/// <summary> /// <see cref="AmfObjectAttribute"/>, , <see cref="AmfMemberAttribute"/>. /// </summary> /// <param name="sourceObjects"> .</param> /// <returns></returns> private static object[] GenerateType(object[] sourceObjects) { for (int i = 0; i < sourceObjects.Length; i++) sourceObjects[i] = GenerateType(sourceObjects[i]); // . return sourceObjects; }
ããã§ããµãŒããŒã«ããã«éä¿¡ããããã«ããªããžã§ã¯ããšé
åãAMFã«ã·ãªã¢ã«åã§ããŸãã ãã ããCïŒã«ã¯ãªãé£æ³AMFé
åãéä¿¡ã§ããæ©èœãå¿
èŠã§ãã ããã§ã®é£æ³é
åã¯ã
IEnumerable <KeyValuePair <TKeyãTValue>èŸæžã®ããŸããŸãªå®è£
ã§ããã
Hashtableããã·ã¥ããŒãã«ã§ããAMFã¯ãåèŸæžããŒãé
ååã®ãã£ãŒã«ããšããŠèªèããŸãã
ãã®åé¡ã®è§£æ±ºçãå®è£
ããããã«ãèŸæžã®ããŒãšå€ã«åºã¥ããŠAMFèŸæžãæ£ããçæã§ããå¥ã®ãªãŒããŒããŒããäœæããŸãã /// <summary> /// , . , object, , AMF. /// </summary> /// <param name="sourceType"> .</param> /// <returns></returns> private static bool IsDictionary(this Type sourceType) { Type type0 = typeof(IEnumerable<KeyValuePair<string, object>>); Type type1 = typeof(IDictionary<string, object>); Type type2 = typeof(Dictionary<string, object>); return sourceType.FullName == type0.FullName || sourceType.IsSubclassOf(type0) || sourceType.FullName == type1.FullName || sourceType.IsSubclassOf(type1) || sourceType.FullName == type2.FullName || sourceType.IsSubclassOf(type2); } /// <summary> /// "-", , - . /// </summary> /// <param name="fields"> "-"</param> /// <returns></returns> private static object GenerateType(IEnumerable<KeyValuePair<string, object>> fields) { AssemblyName assemblyName = new AssemblyName("AmfDynamicAssemblyForDictionary"); // . AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave); // . ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name, assemblyName.Name + ".dll"); // . TypeBuilder typeBuilder = moduleBuilder.DefineType(typeof(Array).FullName, TypeAttributes.Public); // . ConstructorBuilder ctor = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, Type.EmptyTypes); // . ILGenerator ctorIL = ctor.GetILGenerator(); // MSIL- . ctorIL.Emit(OpCodes.Ldarg_0); // . ctorIL.Emit(OpCodes.Call, typeof(object).GetConstructor(Type.EmptyTypes)); // . ctorIL.Emit(OpCodes.Ret); // . // . foreach (KeyValuePair<string, object> pair in fields) { object fieldValue = pair.Value; // . Type fieldType = fieldValue.GetType(); // . // ... if (fieldType.IsDefinedAttribute<AmfObjectAttribute>()) { fieldValue = GenerateType(fieldValue); // , . fieldType = fieldValue.GetType(); // . } typeBuilder.DefineField(pair.Key, fieldType, FieldAttributes.Public); // . } object targetObject = Activator.CreateInstance(typeBuilder.CreateType()); // . // . foreach (KeyValuePair<string, object> pair in fields) targetObject.GetType().GetField(pair.Key).SetValue(targetObject, pair.Value); return targetObject; }
ããã§ãã¡ãœãããåŒã³åºããã³ã«åå¥ã®åçã¢ã»ã³ããªãäœæãããã®ã¡ã¿ããŒã¿ããªãŒããŒã©ã€ãããããšã«æ³šæããŠãã ãããããã¯ããã£ã¯ã·ã§ããªã®ãã¹ãŠã®ã¡ã¿ããŒã¿ãæ°ãã«çæããããã«å¿
èŠã§ããããããªããšããã°ãããããšããã£ã¯ã·ã§ããªã®ã³ããŒã«ãã¿ã€ãã«å«ãŸããŠã¯ãªãããã¡ã¢ãªç©ºéãå æããæªå®çŸ©ãã£ãŒã«ãã倧éã«å«ãŸããŸããAMFã·ãªã¢ã«å
ããã§ãAMFã§ãªããžã§ã¯ããã·ãªã¢ã«åããæºåããã¹ãŠæŽããŸãããã·ãªã¢ã©ã€ã¶ãŒã®å®è£
ã«é²ã¿ãŸãã /// <summary> /// AMF. /// </summary> /// <param name="sourceObject"> .</param> /// <param name="version"> AMF.</param> /// <returns></returns> public static byte[] SerializeToAmf(this object sourceObject, ushort version) { using (MemoryStream memoryStream = new MemoryStream()) // . using (AMFSerializer amfSerializer = new AMFSerializer(memoryStream)) // AMF. { AMFMessage amfMessage = new AMFMessage(version); // AMF. AMFBody amfBody = new AMFBody(AMFBody.OnResult, null, GenerateType(sourceObject)); // AMF. amfMessage.AddBody(amfBody); // body AMF. amfSerializer.WriteMessage(amfMessage); // . return memoryStream.ToArray(); // . } } /// <summary> /// AMF3. /// </summary> /// <param name="sourceObject"> .</param> /// <returns></returns> public static byte[] SerializeToAmf(this object sourceObject) => sourceObject.SerializeToAmf(3); /// <summary> /// *.amf. /// </summary> /// <param name="sourceObject"> .</param> /// <param name="path"> .</param> /// <param name="version"> AMF.</param> public static void SerializeToAmf(this object sourceObject, string path, ushort version) => File.WriteAllBytes($"{path}.amf", sourceObject.SerializeToAmf(version)); /// <summary> /// *.amf. AMF 3. /// </summary> /// <param name="sourceObject"> .</param> /// <param name="path"> .</param> public static void SerializeToAmf(this object sourceObject, string path) => sourceObject.SerializeToAmf(path, 3);
å®è£
ã¯ã»ãšãã©ç°¡åã§ããå¯äžã®æ³šæç¹ã¯ãAMFã®ããã©ã«ãããŒãžã§ã³çªå·ã3ã§ãããªãŒããŒããŒããæå³çã«äœæããããšã§ããFlexã䜿çšããå Žåãã»ãšãã©ã®å ŽåAMF3ã§ããã€ãŸããã·ãªã¢ã«åã¡ãœããã®åŒã³åºãã§è¿œå ã®åŒæ°ãæž¡ãããšã¯æå³ããããŸãããéã·ãªã¢ã«åãè¡ãã«ã¯ãäžèšã®æé ããã¹ãŠéã®é åºã§è¡ãå¿
èŠããããŸãã /// <summary> /// AMF. /// </summary> /// <typeparam name="T"> .</typeparam> /// <param name="sourceBuffer"> .</param> /// <returns></returns> public static T DeserializeFromAmf<T>(this byte[] sourceBuffer) where T : class { using (MemoryStream memoryStream = new MemoryStream(sourceBuffer)) // . using (AMFDeserializer amfDeserializer = new AMFDeserializer(memoryStream)) // AMF. { AMFMessage amfMessage = amfDeserializer.ReadAMFMessage(); // AMF. AMFBody amfBody = amfMessage.GetBodyAt(0); // body AMF. object amfObject = amfBody.Content; // body AMF. Type amfObjectType = amfObject.GetType(); // AMF. // . IEnumerable<Type> types = from type in Assembly.GetExecutingAssembly().GetTypes() where Attribute.IsDefined(type, typeof(AmfObjectAttribute)) select type; Type currentType = null; // . // . foreach (Type type in types) { AmfObjectAttribute attribute = type.GetAttribute<AmfObjectAttribute>(); // . if (attribute == null || attribute.Name != amfObjectType.FullName) continue; // - . currentType = type; // . break; } if (currentType == null) return default(T); // - null. object targetObject = Activator.CreateInstance(currentType); // . // . foreach (PropertyInfo propertyInfo in currentType.GetProperties()) { AmfMemberAttribute attribute = propertyInfo.GetAttribute<AmfMemberAttribute>(); // . if (attribute == null) continue; // - . propertyInfo.SetValue(targetObject, amfObjectType.GetProperty(attribute.Name).GetValue(amfObject, null), null); // . } // . foreach (FieldInfo fieldInfo in currentType.GetFields()) { AmfMemberAttribute attribute = fieldInfo.GetAttribute<AmfMemberAttribute>(); // . if (attribute == null) continue; // - . fieldInfo.SetValue(targetObject, amfObjectType.GetField(attribute.Name).GetValue(amfObject)); // . } return targetObject as T; // T . } } /// <summary> /// *.amf. /// </summary> /// <typeparam name="T"> .</typeparam> /// <param name="obj"> .</param> /// <param name="path"> .</param> /// <returns> AMF.</returns> public static T DeserializeFromAmf<T>(this object obj, string path) where T : class => File.ReadAllBytes($"{path}.amf").DeserializeFromAmf<T>();
次ã«ãAMFã§ãªããžã§ã¯ããã·ãªã¢ã«åããŠãµãŒããŒã«éä¿¡ããæéã®æ¹æ³ã以äžã«ç€ºããŸãã using (MemoryStream memoryStream = new MemoryStream()) // . using (AMFWriter amfWriter = new AMFWriter(memoryStream)) // AMF. using (WebClient client = new WebClient()) // HTTP- ( HttpWebRequest). { amfWriter.WriteBytes(new CustomAmfObject().SerializeToAmf()); // . client.Headers[HttpRequestHeader.ContentType] = "application/x-amf"; // ContentType . byte[] buffer = client.UploadData(Host, "POST", memoryStream.ToArray()); // . }
以äžã®ã¹ã¯ãªãŒã³ã·ã§ããã§ã¯ããµãŒããŒã«éä¿¡ããæºåãã§ããŠããã·ãªã¢ã«åããããªããžã§ã¯ãã®æ§é ã確èªã§ããŸãã
ããŒã¿éä¿¡åŸã®ãµãŒããŒããªããžã§ã¯ããIExternalizableã€ã³ã¿ãŒãã§ã€ã¹ãå®è£
ããŠããªããšèªãå Žåãã«ã¹ã¿ã ã¯ã©ã¹ã«IExternalizableå®è£
ãå®è£
ããå¿
èŠããããŸãïŒ [AmfObject("example.game.gameObject")] public class CustomAmfObject : IExternalizable { [AmfMember("x")] public float X { get; set; } [AmfMember("y")] public float Y { get; set; } [AmfMember("z")] public float Z { get; set; } public CustomAmfObject(float x, float y, float z) { X = x; Y = y; Z = z; } public CustomAmfObject() : this(0f, 0f, 0f) { } public void ReadExternal(IDataInput input) { X = input.ReadFloat(); Y = input.ReadFloat(); Z = input.ReadFloat(); } public void WriteExternal(IDataOutput output) { output.WriteFloat(X); output.WriteFloat(Y); output.WriteFloat(Z); } }
ãã¹ããå®éã®æ¡ä»¶ã§ç€ºããããã«ããã®ã¢ãããŒãã§ããŒã¿ãã·ãªã¢ã«åããããã«ãIDataOutputã®äžé£ã®ã¬ã³ãŒããšIDataInputããã®èªã¿åãã¯ãŸã£ããå¿
èŠãªãããããã®ãªãããŒã¿ã¯ãã¹ãŠæ£ãã圢åŒã§ãµãŒããŒã«éä¿¡ãããŸãããç¹ã«ãåªãããµãŒããŒã®å Žåããã®ãœãªã¥ãŒã·ã§ã³ã¯éåžžã«äŸ¿å©ã§ããããšãã
äžèšã®åé¡ã解決ããæ¹æ³ã¯ãå
ã®ãã¬ãŒã ã¯ãŒã¯ã®ãœãŒã¹ã³ãŒããžã®ä»å
¥ãå¿
èŠãšããªãå¯äžã®ãã®ã§ã¯ãããŸãããããšãã°ãDynamicObjectãExpandoObjectãããã³ãã®ä»ã®åçãªéã¢ã¡ããã£ã䜿çšããŠãªããžã§ã¯ãã®ã€ã³ã¹ã¿ã³ã¹ãå®è£
ããã¡ã¿ããŒã¿ã®ãã¹ãŠã®äœæ¥ãDLRã«å²ãåœãŠããšãå±æ§ãªãã§ã³ãŒãã®ã¡ã¿ããŒã¿ãåŠçã§ããŸããèšäºã«èšèŒãããŠããç¥èããŒã¹ã¯ãã»ãšãã©ãã¹ãŠã®ã¿ã¹ã¯ã®ã·ãªã¢ã©ã€ã¶ãŒããŸãã¯MSILãšãªãã¬ã¯ã·ã§ã³ã«åºã¥ãåçŽãªã€ã³ã¿ãŒããªã¿ãŒ/ã³ã³ãã€ã©ãŒãããã³AMFã§ã®ã·ãªã¢ã«åã®åçãããèŠèŠçã«ç解ããã®ã«ååã§ããèšäºã®ãœãŒã¹ã¯ãã¡ãããå
¥æã§ããŸããNuGet FluorineFxæ¡åŒµããã¯ã¯ãã¡ãã«ãããŸããAMFãã·ãªã¢ã«åããã ãã§ããã¹ãŠã®FluorineFXããããžã§ã¯ãã«ãã©ãã°ããå¿
èŠãããå Žåã¯ãããã§ã.NET DataContractã·ãªã¢ã«åã«åºã¥ããŠããããã³ã°ã䜿çšããŠå®è£
ãããArtemAã«ãã£ãŠææ¡ãããã·ãªã¢ã©ã€ã¶ãŒã®ããŒãžã§ã³ãèŠã€ããããšãã§ããŸããç§ãæ瀺ããè³æãããªãã®åœ¹ã«ç«ã€ããšãé¡ã£ãŠããŸãããæž
èŽããããšãããããŸããïŒ