рд░реЛрдЬрд▓рд┐рди рдХреЗ рд╕рд╛рде рдХреЛрдб рдЬрдирд░реЗрд╢рди

рд╕рдордп-рд╕рдордп рдкрд░, рдЬрдм рдореИрдВрдиреЗ рд░реЛрдЬрд▓рд┐рди рдФрд░ рдЗрд╕рдХреЗ рд╡рд┐рд╢реНрд▓реЗрд╖рдгрдХрд░реНрддрд╛рдУрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдкрдврд╝рд╛, рддреЛ рдореИрдВрдиреЗ рд▓рдЧрд╛рддрд╛рд░ рд╕реЛрдЪрд╛ рдерд╛: "рд▓реЗрдХрд┐рди рдЖрдк рдЗрд╕ рдЪреАрдЬрд╝ рдХреЗ рд╕рд╛рде рдирдЧреЗрдЯ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ, рдЬреЛ рдХреЛрдб рдХреЗ рдЖрд╕рдкрд╛рд╕ рдЬрд╛рдПрдЧрд╛ рдФрд░ рдХреЛрдб рдЬрдирд░реЗрд╢рди рдХрд░реЗрдЧрд╛ред" рдПрдХ рддреНрд╡рд░рд┐рдд рдЦреЛрдЬ рдиреЗ рдХреБрдЫ рднреА рджрд┐рд▓рдЪрд╕реНрдк рдирд╣реАрдВ рджрд┐рдЦрд╛рдпрд╛, рдЗрд╕рд▓рд┐рдП рдЦреБрджрд╛рдИ рдХрд░рдиреЗ рдХрд╛ рдирд┐рд░реНрдгрдп рд▓рд┐рдпрд╛ рдЧрдпрд╛ред рдЬрдм рдореБрдЭреЗ рдкрддрд╛ рдЪрд▓рд╛ рдХрд┐ рдореБрдЭреЗ рдХрд┐рддрдирд╛ рд╕реБрдЦрдж рдЖрд╢реНрдЪрд░реНрдп рд╣реБрдЖ, рддреЛ рдореЗрд░рд╛ рд╡рд┐рдЪрд╛рд░ рдХреЗрд╡рд▓ рд╕рдВрднрд╡ рдирд╣реАрдВ рдерд╛, рд▓реЗрдХрд┐рди рдпрд╣ рд╕рдм рд▓рдЧрднрдЧ рдмрд┐рдирд╛ рдмреИрд╕рд╛рдЦреА рдХреЗ рдХрд╛рдо рдХрд░реЗрдЧрд╛ред


рдФрд░ рдЗрд╕рд▓рд┐рдП рдЬреЛ рдпрд╣ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдЗрдЪреНрдЫреБрдХ рд╣реИ рдХрд┐ рдЖрдк "рдЫреЛрдЯрд╛ рдкреНрд░рддрд┐рдмрд┐рдВрдм" рдХреИрд╕реЗ рдмрдирд╛ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕реЗ рдмрд┐рд▓реНрд▓реА рдХреЗ рдиреАрдЪреЗ, рдирдЧреЗрдЯ рдореЗрдВ рдкреИрдХ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред


рдкрд░рд┐рдЪрдп


рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рд╕реНрдкрд╖реНрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд╣рд▓реА рдмрд╛рдд рдпрд╣ рд╣реИ рдХрд┐ "рдереЛрдбрд╝рд╛ рдкреНрд░рддрд┐рдмрд┐рдВрдм" рд╕реЗ рдХреНрдпрд╛ рдорддрд▓рдм рд╣реИред рдореИрдВ рд╕рднреА рдкреНрд░рдХрд╛рд░ рдХреЗ Dictionary<string, Type> GetBakedType() рд╡рд┐рдзрд┐ рдХреЗ рд▓рд┐рдП рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХрд╛ рд╕реБрдЭрд╛рд╡ рджреЗрддрд╛ рд╣реВрдВ, рдЬреЛ рдЧреБрдгреЛрдВ рдФрд░ рдЙрдирдХреЗ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рдирд╛рдо рд╡рд╛рдкрд╕ рдХрд░ рджреЗрдЧрд╛ред рдЪреВрдВрдХрд┐ рдпрд╣ рд╕рднреА рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП, рдЗрд╕рд▓рд┐рдП рд╕рдмрд╕реЗ рдЖрд╕рд╛рди рд╡рд┐рдХрд▓реНрдк рдкреНрд░рддреНрдпреЗрдХ рдкреНрд░рдХрд╛рд░ рдХреЗ рд▓рд┐рдП рдПрдХ рдирд┐рд░реЛрдз рд╡рд┐рдзрд┐ рдЙрддреНрдкрдиреНрди рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рдЗрд╕рдХреЗ рдореИрдиреБрдЕрд▓ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЗ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд░реВрдк рд╣реЛрдВрдЧреЗ:


 using System; using System.Collections.Generic; public static class testSimpleReflectionUserExtentions { private static Dictionary<string, Type> properties = new Dictionary<string, Type> { { "Id", typeof(System.Guid)}, { "FirstName", typeof(string)}, { "LastName", typeof(string)}, }; public static Dictionary<string, Type> GetBakedType(this global::testSimpleReflection.User value) { return properties; } } 

рдпрд╣рд╛рдВ рдХреБрдЫ рднреА рдЕрд▓реМрдХрд┐рдХ рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рд╕рднреА рдкреНрд░рдХрд╛рд░реЛрдВ рдХреЗ рд▓рд┐рдП рдЗрд╕реЗ рдорд╣рд╕реВрд╕ рдХрд░рдирд╛ рдПрдХ рдиреАрд░рд╕ рдФрд░ рджрд┐рд▓рдЪрд╕реНрдк рд╡реНрдпрд╡рд╕рд╛рдп рдирд╣реАрдВ рд╣реИ, рдЬреЛ рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЯрд╛рдЗрдкрдХреЛрд╕ рдХреЛ рдЦрддрд░рд╛ рд╣реИред рд╣рдо рдорджрдж рдХреЗ рд▓рд┐рдП рд╕рдВрдХрд▓рдХ рд╕реЗ рдХреНрдпреЛрдВ рдирд╣реАрдВ рдкреВрдЫрддреЗред рдпрд╣ рд╡рд╣ рдЬрдЧрд╣ рд╣реИ рдЬрд╣рд╛рдБ рд░реЛрдЬрд▓рд┐рди рдФрд░ рдЙрд╕рдХреЗ рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рдЕрдЦрд╛рдбрд╝реЗ рдореЗрдВ рдкреНрд░рд╡реЗрд╢ рдХрд░рддреЗ рд╣реИрдВред рд╡реЗ рдХреЛрдб рдХрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░рдиреЗ рдФрд░ рдЗрд╕реЗ рдмрджрд▓рдиреЗ рдХрд╛ рдЕрд╡рд╕рд░ рдкреНрд░рджрд╛рди рдХрд░рддреЗ рд╣реИрдВред рддреЛ рдЪрд▓рд┐рдП рдХрдВрдкрд╛рдЗрд▓рд░ рдХреЛ рдПрдХ рдирдИ рдЯреНрд░рд┐рдХ рд╕рд┐рдЦрд╛рддреЗ рд╣реИрдВред рдЙрд╕реЗ рдХреЛрдб рдХреЗ рдЪрд╛рд░реЛрдВ рдУрд░ рдЬрд╛рдиреЗ рджреЗрдВ рдФрд░ рджреЗрдЦреЗрдВ рдХрд┐ рд╣рдо рдХрд╣рд╛рдВ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рдЕрднреА рддрдХ рд╣рдорд╛рд░реЗ GetBakedType рд▓рд╛рдЧреВ рдирд╣реАрдВ рдХрд┐рдпрд╛ рд╣реИ рдФрд░ рдЗрд╕реЗ рд▓рд╛рдЧреВ рдХрд░рддрд╛ рд╣реИред


рдЗрд╕ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЛ "рд╕рдХреНрд╖рдо" рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ рдХреЗрд╡рд▓ рдПрдХ рдирдЧреЗрдЯ рдкреИрдХреЗрдЬ рд╕реНрдерд╛рдкрд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдФрд░ рд╕рдм рдХреБрдЫ рддреБрд░рдВрдд рдХрд╛рдо рдХрд░реЗрдЧрд╛ред рдЕрдЧрд▓рд╛, рдмрд╕ GetBakedType рдХреЙрд▓ рдХрд░реЗрдВ рдЬрд╣рд╛рдВ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ, рд╣рдореЗрдВ рдПрдХ рд╕рдВрдХрд▓рди рддреНрд░реБрдЯрд┐ рдорд┐рд▓рддреА рд╣реИ рдЬреЛ рдХрд╣рддреА рд╣реИ рдХрд┐ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдХреЗ рд▓рд┐рдП рдкреНрд░рддрд┐рдмрд┐рдВрдм рдЕрднреА рддреИрдпрд╛рд░ рдирд╣реАрдВ рд╣реИ, рдХреЛрдбрдлрд┐рдХреНрд╕ рдХреЛ рдХреЙрд▓ рдХрд░реЗрдВ рдФрд░ рдЖрдкрдХрд╛ рдХрд╛рдо рд╣реЛ рдЧрдпрд╛ред рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рд╡рд┐рд╕реНрддрд╛рд░ рд╡рд┐рдзрд┐ рд╣реИ рдЬреЛ рд╕рднреА рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рд╕рдВрдкрддреНрддрд┐рдпреЛрдВ рдХреЛ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд▓реМрдЯрд╛ рджреЗрдЧреАред


рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдЖрдВрджреЛрд▓рди рдореЗрдВ рдпрд╣ рд╕рдордЭрдирд╛ рдЖрд╕рд╛рди рд╣реЛрдЧрд╛ рдХрд┐ рдпрд╣ рдЖрдо рддреМрд░ рдкрд░ рдХреИрд╕реЗ рдХрд╛рдо рдХрд░рддрд╛ рд╣реИ, рдпрд╣рд╛рдВ рдПрдХ рдЫреЛрдЯрд╛ рджреГрд╢реНрдп рд╣реИ:



рд╕реНрдерд╛рдиреАрдп рд░реВрдк рд╕реЗ рдЗрд╕реЗ рдЖрдЬрд╝рдорд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЗрдЪреНрдЫреБрдХ рдХреЛрдИ рднреА рд╡реНрдпрдХреНрддрд┐ рд╕рд░рд▓ рдирд╛рдо рдХреЗ рддрд╣рдд рдирдЧреЗрдЯ рдкреИрдХреЗрдЬ рд╕реНрдерд╛рдкрд┐рдд рдХрд░ рд╕рдХрддрд╛ рд╣реИ:


 Install-Package SimpleReflection 

рдЬреЛ рд╕реНрд░реЛрдд рдХреА рдкрд░рд╡рд╛рд╣ рдХрд░рддреЗ рд╣реИрдВ, рд╡реЗ рдпрд╣рд╛рдВ рд╣реИрдВ ред


рдореИрдВ рдЪреЗрддрд╛рд╡рдиреА рджреЗрдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВ рдХрд┐ рдпрд╣ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдЙрдкрдпреЛрдЧ рдХреЗ рд▓рд┐рдП рдирд╣реАрдВ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИред рдореИрдВ рд╕рд┐рд░реНрдл рд░реЛрдЬрд▓рд┐рди рдХреЗ рд╕рд╛рде рдХреЛрдб рдЬреЗрдирд░реЗрд╢рди рдХреЛ рд╡реНрдпрд╡рд╕реНрдерд┐рдд рдХрд░рдиреЗ рдХрд╛ рдПрдХ рддрд░реАрдХрд╛ рджрд┐рдЦрд╛рдирд╛ рдЪрд╛рд╣рддрд╛ рд╣реВрдВред


рдкреНрд░рд╛рд░рдВрднрд┐рдХ рддреИрдпрд╛рд░реА


рдЗрд╕рд╕реЗ рдкрд╣рд▓реЗ рдХрд┐ рдЖрдк рдЕрдкрдиреЗ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░реЗрдВ, рдЖрдкрдХреЛ рд╕реНрдЯреВрдбрд┐рдпреЛ рдЗрдВрд╕реНрдЯреЙрд▓рд░ рдореЗрдВ рдШрдЯрдХ ext рд╡рд┐рдЬрд╝реБрдЕрд▓ рд╕реНрдЯреВрдбрд┐рдпреЛ рдПрдХреНрд╕реНрдЯреЗрдВрд╢рди рдбреЗрд╡рд▓рдкрдореЗрдВрдЯ тАЩрд╕реНрдерд╛рдкрд┐рдд рдХрд░рдирд╛ рд╣реЛрдЧрд╛ред рд╡реАрдПрд╕ 2019 рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рд╡реИрдХрд▓реНрдкрд┐рдХ рдШрдЯрдХ рдХреЗ рд░реВрдк рдореЗрдВ ".NET рдХрдВрдкрд╛рдЗрд▓рд░ рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рдПрд╕рдбреАрдХреЗ" рдХрд╛ рдЪрдпрди рдХрд░рдирд╛ рдпрд╛рдж рд░рдЦрдирд╛ рдЪрд╛рд╣рд┐рдПред


рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди


рдореИрдВ рдЪрд░рдгреЛрдВ рдореЗрдВ рд╡рд░реНрдгрди рдирд╣реАрдВ рдХрд░реВрдВрдЧрд╛ рдХрд┐ рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рдХреЛ рдХреИрд╕реЗ рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рдП, рдХреНрдпреЛрдВрдХрд┐ рдпрд╣ рдмрд╣реБрдд рд╕рд░рд▓ рд╣реИ, рд▓реЗрдХрд┐рди рд╕рд┐рд░реНрдл рдкреНрд░рдореБрдЦ рдмрд┐рдВрджреБрдУрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЬрд╛рдирд╛ред


рдФрд░ рдкрд╣рд▓рд╛ рдореБрдЦреНрдп рдмрд┐рдВрджреБ рдпрд╣ рд╣реЛрдЧрд╛ рдХрд┐ рдпрджрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╕рдВрдХрд▓рди рддреНрд░реБрдЯрд┐ рд╣реИ, рддреЛ рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рдмрд┐рд▓реНрдХреБрд▓ рднреА рд╢реБрд░реВ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВред рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк, рдпрджрд┐ рд╣рдо рдЕрдкрдиреЗ GetBakedType() рдХреЛ рдЙрд╕ рдкреНрд░рдХрд╛рд░ рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рдХреЙрд▓ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ рдЬрд┐рд╕рдХреЗ рд▓рд┐рдП рдЗрд╕реЗ рд▓рд╛рдЧреВ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рддреЛ рд╣рдореЗрдВ рд╕рдВрдХрд▓рди рддреНрд░реБрдЯрд┐ рдорд┐рд▓реЗрдЧреА рдФрд░ рд╣рдорд╛рд░реЗ рд╕рднреА рдкреНрд░рдпрд╛рд╕реЛрдВ рдХрд╛ рдХреЛрдИ рдорддрд▓рдм рдирд╣реАрдВ рд╣реЛрдЧрд╛ред рд▓реЗрдХрд┐рди рдпрд╣рд╛рдВ рд╣рдореЗрдВ рдЙрд╕ рдкреНрд░рд╛рдердорд┐рдХрддрд╛ рдХреЗ рдЬреНрдЮрд╛рди рд╕реЗ рдорджрдж рдХреА рдЬрд╛рдПрдЧреА рдЬрд┐рд╕рдХреЗ рд╕рд╛рде рдХрдВрдкрд╛рдЗрд▓рд░ рдПрдХреНрд╕рдЯреЗрдВрд╢рди рд╡рд┐рдзрд┐рдпреЛрдВ рдХреЛ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИред рдкреВрд░реЗ рдмрд┐рдВрджреБ рдпрд╣ рд╣реИ рдХрд┐ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рд╕рд╛рдорд╛рдиреНрдп рддрд░реАрдХреЛрдВ рдкрд░ рд╡рд░реАрдпрддрд╛ рд▓реЗрддреЗ рд╣реИрдВред рдЕрд░реНрдерд╛рддреН, рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рджреВрд╕рд░реА рд╡рд┐рдзрд┐ рдХреЛ рдмреБрд▓рд╛рдпрд╛ рдЬрд╛рдПрдЧрд╛, рди рдХрд┐ рдкрд╣рд▓реА:


 public static class SomeExtentions { public static void Save<T>(this T value) { ... } public static void Save(this User user) { ... } } public class Program { public static void Main(string[] args) { var user = new User(); user.Save(); } } 

рдпрд╣ рд╕реБрд╡рд┐рдзрд╛ рдмрд╣реБрдд рдЖрд╕рд╛рди рд╣реИред рд╣рдо рдХреЗрд╡рд▓ рд╕рд╛рдорд╛рдиреНрдп GetBakedType рдХреЛ рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ:


 using System; using System.Collections.Generic; public static class StubExtention { public static Dictionary<string, Type> GetBakedType<TValue>(this TValue value) { return new Dictionary<string, Type>(); } } 

рдпрд╣ рд╣рдореЗрдВ рдмрд╣реБрдд рд╢реБрд░реБрдЖрдд рдореЗрдВ рдПрдХ рд╕рдВрдХрд▓рди рддреНрд░реБрдЯрд┐ рд╕реЗ рдмрдЪрдиреЗ рдФрд░ рдЕрдкрдиреА рдЦреБрдж рдХреА рд╕рдВрдХрд▓рди "рддреНрд░реБрдЯрд┐" рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрдЧрд╛ред


рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рдЦреБрдж рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред рд╡рд╣ рджреЛ рдирд┐рджрд╛рди рдХреА рдкреЗрд╢рдХрд╢ рдХрд░реЗрдЧрд╛ред рдкрд╣рд▓рд╛ рдЙрд╕ рдорд╛рдорд▓реЗ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рд╣реИ рдЬрдм рдХреЛрдб рдкреАрдврд╝реА рдмрд┐рд▓реНрдХреБрд▓ рднреА рд╢реБрд░реВ рдирд╣реАрдВ рд╣реБрдИ рдереА, рдФрд░ рджреВрд╕рд░рд╛ рдЬрдм рд╣рдореЗрдВ рдХрд┐рд╕реА рдореМрдЬреВрджрд╛ рдХреЛрдб рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдЙрдирдХреЗ рдкрд╛рд╕ рдХреНрд░рдорд╢рдГ SimpleReflectionIsNotReady рдФрд░ SimpleReflectionUpdate рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдирд╛рдо рд╣реЛрдВрдЧреЗред рдкрд╣рд▓рд╛ рдбрд╛рдпрдЧреНрдиреЛрд╕реНрдЯрд┐рдХреНрд╕ рдПрдХ "рд╕рдВрдХрд▓рди рддреНрд░реБрдЯрд┐" рдЙрддреНрдкрдиреНрди рдХрд░реЗрдЧрд╛, рдФрд░ рджреВрд╕рд░рд╛ рдХреЗрд╡рд▓ рд░рд┐рдкреЛрд░реНрдЯ рдХрд░рддрд╛ рд╣реИ рдХрд┐ рдпрд╣рд╛рдВ рдЖрдк рдХреЛрдб рдкреАрдврд╝реА рдлрд┐рд░ рд╕реЗ рдЪрд▓рд╛ рд╕рдХрддреЗ рд╣реИрдВред


рдирд┐рджрд╛рди рдХрд╛ рд╡рд┐рд╡рд░рдг рдЗрд╕ рдкреНрд░рдХрд╛рд░ рд╣реИ:


  public const string SimpleReflectionIsNotReady = "SimpleReflectionIsNotReady"; public const string SimpleReflectionUpdate = "SimpleReflectionUpdate"; public static DiagnosticDescriptor SimpleReflectionIsNotReadyDescriptor = new DiagnosticDescriptor( SimpleReflectionIsNotReady, "Simple reflection is not ready.", "Simple reflection is not ready.", "Codegen", DiagnosticSeverity.Error, isEnabledByDefault: true, "Simple reflection is not ready."); public static DiagnosticDescriptor SimpleReflectionUpdateDescriptor = new DiagnosticDescriptor( SimpleReflectionUpdate, "Simple reflection update.", "Simple reflection update.", "Codegen", DiagnosticSeverity.Info, isEnabledByDefault: true, "Simple reflection update."); 

рдЕрдЧрд▓рд╛, рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ рдХрд┐ рд╣рдо рдХреНрдпрд╛ рдЦреЛрдЬ рд░рд╣реЗ рд╣реИрдВ, рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ рдпрд╣ рдПрдХ рд╡рд┐рдзрд┐ рдХреЙрд▓ рд╣реЛрдЧреА:


 public override void Initialize(AnalysisContext context) { context.RegisterOperationAction(this.HandelBuilder, OperationKind.Invocation); } 

рдлрд┐рд░ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА HandelBuilder рдореЗрдВ рдПрдХ рд╡рд╛рдХреНрдпрд╡рд┐рдиреНрдпрд╛рд╕ рдЯреНрд░реА рд╡рд┐рд╢реНрд▓реЗрд╖рдг рд╣реИред рдкреНрд░рд╡реЗрд╢ рджреНрд╡рд╛рд░ рдкрд░ рд╣рдореЗрдВ рд╡реЗ рд╕рднреА рдХреЙрд▓ рдкреНрд░рд╛рдкреНрдд рд╣реЛрдВрдЧреА рдЬреЛ рдЖрдкрдХреЛ рдорд┐рд▓реА рдереАрдВ, рдЗрд╕рд▓рд┐рдП рдЖрдкрдХреЛ рд╣рдорд╛рд░реЗ GetBakedType рдХреЛ рдЫреЛрдбрд╝рдХрд░ рд╕рдм рдХреБрдЫ рд╕рдорд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдпрд╣ рд╕рд╛рдорд╛рдиреНрдп рдХреЗ рд╕рд╛рде рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ if рд╣рдо рд╡рд┐рдзрд┐ рдХреЗ рдирд╛рдо рдХреА рдЬрд╛рдВрдЪ рдХрд░рддреЗ рд╣реИрдВред рдЖрдЧреЗ рд╣рдореЗрдВ рдЙрд╕ рдкреНрд░рдХрд╛рд░ рдХрд╛ рд╡реИрд░рд┐рдПрдмрд▓ рдорд┐рд▓рддрд╛ рд╣реИ, рдЬрд┐рд╕ рдкрд░ рд╣рдорд╛рд░реА рд╡рд┐рдзрд┐ рдХрд╣рд▓рд╛рддреА рд╣реИ рдФрд░ рдХрдВрдкрд╛рдЗрд▓рд░ рдХреЛ рд╣рдорд╛рд░реЗ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХреЗ рдкрд░рд┐рдгрд╛рдореЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рд╕реВрдЪрд┐рдд рдХрд░рддреА рд╣реИред рдпрд╣ рдПрдХ рд╕рдВрдХрд▓рди рддреНрд░реБрдЯрд┐ рд╣реЛ рд╕рдХрддреА рд╣реИ рдпрджрд┐ рдХреЛрдб рдкреАрдврд╝реА рдЕрднреА рддрдХ рд╢реБрд░реВ рдирд╣реАрдВ рд╣реБрдИ рд╣реИ рдпрд╛ рдЗрд╕реЗ рдкреБрдирд░рд╛рд░рдВрдн рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдирд╣реАрдВ рд╣реИред


рдпрд╣ рд╕рдм рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:


 private void HandelBuilder(OperationAnalysisContext context) { if (context.Operation.Syntax is InvocationExpressionSyntax invocation && invocation.Expression is MemberAccessExpressionSyntax memberAccess && memberAccess.Name is IdentifierNameSyntax methodName && methodName.Identifier.ValueText == "GetBakedType") { var semanticModel = context.Compilation .GetSemanticModel(invocation.SyntaxTree); var typeInfo = semanticModel .GetSpeculativeTypeInfo(memberAccess.Expression.SpanStart, memberAccess.Expression, SpeculativeBindingOption.BindAsExpression); var diagnosticProperties = ImmutableDictionary<string, string>.Empty.Add("type", typeInfo.Type.ToDisplayString()); if (context.Compilation.GetTypeByMetadataName(typeInfo.Type.GetSimpleReflectionExtentionTypeName()) is INamedTypeSymbol extention) { var updateDiagnostic = Diagnostic.Create(SimpleReflectionUpdateDescriptor, methodName.GetLocation(), diagnosticProperties); context.ReportDiagnostic(updateDiagnostic); return; } var diagnostic = Diagnostic.Create(SimpleReflectionIsNotReadyDescriptor, methodName.GetLocation(), diagnosticProperties); context.ReportDiagnostic(diagnostic); } } 

рдкреВрд░реНрдг рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рдХреЛрдб
  [DiagnosticAnalyzer(LanguageNames.CSharp)] public class SimpleReflectionAnalyzer : DiagnosticAnalyzer { public const string SimpleReflectionIsNotReady = "SimpleReflectionIsNotReady"; public const string SimpleReflectionUpdate = "SimpleReflectionUpdate"; public static DiagnosticDescriptor SimpleReflectionIsNotReadyDescriptor = new DiagnosticDescriptor( SimpleReflectionIsNotReady, "Simple reflection is not ready.", "Simple reflection is not ready.", "Codegen", DiagnosticSeverity.Error, isEnabledByDefault: true, "Simple reflection is not ready."); public static DiagnosticDescriptor SimpleReflectionUpdateDescriptor = new DiagnosticDescriptor( SimpleReflectionUpdate, "Simple reflection update.", "Simple reflection update.", "Codegen", DiagnosticSeverity.Info, isEnabledByDefault: true, "Simple reflection update."); public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(SimpleReflectionIsNotReadyDescriptor, SimpleReflectionUpdateDescriptor); public override void Initialize(AnalysisContext context) { context.RegisterOperationAction(this.HandelBuilder, OperationKind.Invocation); } private void HandelBuilder(OperationAnalysisContext context) { if (context.Operation.Syntax is InvocationExpressionSyntax invocation && invocation.Expression is MemberAccessExpressionSyntax memberAccess && memberAccess.Name is IdentifierNameSyntax methodName && methodName.Identifier.ValueText == "GetBakedType" ) { var semanticModel = context.Compilation .GetSemanticModel(invocation.SyntaxTree); var typeInfo = semanticModel .GetSpeculativeTypeInfo(memberAccess.Expression.SpanStart, memberAccess.Expression, SpeculativeBindingOption.BindAsExpression); var diagnosticProperties = ImmutableDictionary<string, string>.Empty.Add("type", typeInfo.Type.ToDisplayString()); if (context.Compilation.GetTypeByMetadataName(typeInfo.Type.GetSimpleReflectionExtentionTypeName()) is INamedTypeSymbol extention) { var updateDiagnostic = Diagnostic.Create(SimpleReflectionUpdateDescriptor, methodName.GetLocation(), diagnosticProperties); context.ReportDiagnostic(updateDiagnostic); return; } var diagnostic = Diagnostic.Create(SimpleReflectionIsNotReadyDescriptor, methodName.GetLocation(), diagnosticProperties); context.ReportDiagnostic(diagnostic); } } } 

рдХреЛрдб рдЬрдирд░реЗрдЯрд░ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди


рд╣рдо CodeFixProvider рдорд╛рдзреНрдпрдо рд╕реЗ CodeFixProvider рдЬреЗрдирд░реЗрд╢рди CodeFixProvider , рдЬреЛ рд╣рдорд╛рд░реЗ рдПрдирд╛рд▓рд╛рдЗрдЬрд░ рдХреЛ рд╕рдмреНрд╕рдХреНрд░рд╛рдЗрдм рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдореЗрдВ рдпрд╣ рдЬрд╛рдВрдЪрдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ рдХрд┐ рд╣рдорд╛рд░реЗ рд╡рд┐рд╢реНрд▓реЗрд╖рдХ рдХреЛ рдЦреЛрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рдХреНрдпрд╛ рд╣реБрдЖред


рдпрд╣ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрддрд╛ рд╣реИ:


 public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { var diagnostic = context.Diagnostics.First(); var title = diagnostic.Severity == DiagnosticSeverity.Error ? "Generate simple reflection" : "Recreate simple reflection"; context.RegisterCodeFix( CodeAction.Create( title, createChangedDocument: token => this.CreateFormatterAsync(context, diagnostic, token), equivalenceKey: title), diagnostic); } 

рд╕рднреА рдЬрд╛рджреВ CreateFormatterAsync рдЕрдВрджрд░ рд╣реЛрддрд╛ рд╣реИред рдЗрд╕рдореЗрдВ рд╣рдореЗрдВ рдЯрд╛рдЗрдк рдХрд╛ рдкреВрд░рд╛ рд╡рд┐рд╡рд░рдг рдорд┐рд▓рддрд╛ рд╣реИред рдлрд┐рд░ рд╣рдо рдХреЛрдб рдкреАрдврд╝реА рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ рдПрдХ рдирдИ рдлрд╝рд╛рдЗрд▓ рдЬреЛрдбрд╝рддреЗ рд╣реИрдВред


рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдФрд░ рдлрд╝рд╛рдЗрд▓ рдЬреЛрдбрд╝рдирд╛:


  private async Task<Document> CreateFormatterAsync(CodeFixContext context, Diagnostic diagnostic, CancellationToken token) { var typeName = diagnostic.Properties["type"]; var currentDocument = context.Document; var model = await context.Document.GetSemanticModelAsync(token); var symbol = model.Compilation.GetTypeByMetadataName(typeName); var rawSource = this.BuildSimpleReflection(symbol); var source = Formatter.Format(SyntaxFactory.ParseSyntaxTree(rawSource).GetRoot(), new AdhocWorkspace()).ToFullString(); var fileName = $"{symbol.GetSimpleReflectionExtentionTypeName()}.cs"; if (context.Document.Project.Documents.FirstOrDefault(o => o.Name == fileName) is Document document) { return document.WithText(SourceText.From(source)); } var folders = new[] { "SimpeReflection" }; return currentDocument.Project .AddDocument(fileName, source) .WithFolders(folders); } 

рдЦреБрдж рдХрд╛ рдХреЛрдб рдЬрдирд░реЗрд╢рди (рдореБрдЭреЗ рд╕рдВрджреЗрд╣ рд╣реИ рдХрд┐ рд╣рдм рдкреВрд░реЗ рд╕рдмрдиреЗрдЯ рдХреЛ рддреЛрдбрд╝ рджреЗрдЧрд╛):


 private string BuildSimpleReflection(INamedTypeSymbol symbol) => $@" using System; using System.Collections.Generic; // Simple reflection for {symbol.ToDisplayString()} public static class {symbol.GetSimpleReflectionExtentionTypeName()} {{ private static Dictionary<string, Type> properties = new Dictionary<string, Type> {{ { symbol .GetAllMembers() .OfType<IPropertySymbol>() .Where(o => (o.DeclaredAccessibility & Accessibility.Public) > 0) .Select(o => $@" {{ ""{o.Name}"", typeof({o.Type.ToDisplayString()})}},") .JoinWithNewLine() } }}; public static Dictionary<string, Type> GetBakedType(this global::{symbol.ToDisplayString()} value) {{ return properties; }} }} "; } 

рдкреВрд░рд╛ рдХреЛрдб рдЬрдирд░реЗрдЯрд░
 using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.Formatting; using Microsoft.CodeAnalysis.Text; using SimpleReflection.Utils; using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Composition; using System.IO; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace SimpleReflection { [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(SimpleReflectionCodeFixProvider)), Shared] public class SimpleReflectionCodeFixProvider : CodeFixProvider { public sealed override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(SimpleReflectionAnalyzer.SimpleReflectionIsNotReady, SimpleReflectionAnalyzer.SimpleReflectionUpdate); public sealed override FixAllProvider GetFixAllProvider() { return WellKnownFixAllProviders.BatchFixer; } public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) { var diagnostic = context.Diagnostics.First(); var title = diagnostic.Severity == DiagnosticSeverity.Error ? "Generate simple reflection" : "Recreate simple reflection"; context.RegisterCodeFix( CodeAction.Create( title, createChangedDocument: token => this.CreateFormatterAsync(context, diagnostic, token), equivalenceKey: title), diagnostic); } private async Task<Document> CreateFormatterAsync(CodeFixContext context, Diagnostic diagnostic, CancellationToken token) { var typeName = diagnostic.Properties["type"]; var currentDocument = context.Document; var model = await context.Document.GetSemanticModelAsync(token); var symbol = model.Compilation.GetTypeByMetadataName(typeName); var symbolName = symbol.ToDisplayString(); var rawSource = this.BuildSimpleReflection(symbol); var source = Formatter.Format(SyntaxFactory.ParseSyntaxTree(rawSource).GetRoot(), new AdhocWorkspace()).ToFullString(); var fileName = $"{symbol.GetSimpleReflectionExtentionTypeName()}.cs"; if (context.Document.Project.Documents.FirstOrDefault(o => o.Name == fileName) is Document document) { return document.WithText(SourceText.From(source)); } var folders = new[] { "SimpeReflection" }; return currentDocument.Project .AddDocument(fileName, source) .WithFolders(folders); } private string BuildSimpleReflection(INamedTypeSymbol symbol) => $@" using System; using System.Collections.Generic; // Simple reflection for {symbol.ToDisplayString()} public static class {symbol.GetSimpleReflectionExtentionTypeName()} {{ private static Dictionary<string, Type> properties = new Dictionary<string, Type> {{ { symbol .GetAllMembers() .OfType<IPropertySymbol>() .Where(o => (o.DeclaredAccessibility & Accessibility.Public) > 0) .Select(o => $@" {{ ""{o.Name}"", typeof({o.Type.ToDisplayString()})}},") .JoinWithNewLine() } }}; public static Dictionary<string, Type> GetBakedType(this global::{symbol.ToDisplayString()} value) {{ return properties; }} }} "; } } 

рдкрд░рд┐рдгрд╛рдо


рдирддреАрдЬрддрди, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рд░реЛрд╕рд▓рд┐рди рд╡рд┐рд╢реНрд▓реЗрд╖рдХ-рдХреЛрдб рдЬрдирд░реЗрдЯрд░ рд╣реИ рдЬрд┐рд╕рдХреА рдорджрдж рд╕реЗ рдХреЛрдб рдкреАрдврд╝реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ "рдЫреЛрдЯрд╛" рдкреНрд░рддрд┐рдмрд┐рдВрдм рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред рд╡рд░реНрддрдорд╛рди рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХреЗ рд▓рд┐рдП рдПрдХ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдЖрд╡реЗрджрди рдХреЗ рд╕рд╛рде рдЖрдирд╛ рдореБрд╢реНрдХрд┐рд▓ рд╣реЛрдЧрд╛, рд▓реЗрдХрд┐рди рдЖрд╕рд╛рдиреА рд╕реЗ рд╕реБрд▓рдн рдХреЛрдб рдЬрдирд░реЗрдЯрд░ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдпрд╣ рдПрдХ рдорд╣рд╛рди рдЙрджрд╛рд╣рд░рдг рд╣реЛрдЧрд╛ред рдпрд╣ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХрд┐рд╕реА рднреА рдХреЛрдб рдкреАрдврд╝реА рдХреА рддрд░рд╣ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ, рдЬреЛ рдзрд╛рд░рд╛рд╡рд╛рд╣рд┐рдХ рд▓рд┐рдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реИред рдореИрд╕реЗрдЬрдкреИрдХ рдХреЗ рдореЗрд░реЗ рдкрд░реАрдХреНрд╖рдг рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдиреЗ рдиреАрдпреВрдХреЗрдХ / рдореИрд╕реЗрдЬрдкреИрдХ-рд╕реАрдПрд╕рдПрдЖрд░рдкреА рдХреА рддреБрд▓рдирд╛ рдореЗрдВ ~ 20% рдЕрдзрд┐рдХ рддреЗрдЬреА рд╕реЗ рдХрд╛рдо рдХрд┐рдпрд╛, рдФрд░ рдореИрдВрдиреЗ рдЕрднреА рддрдХ рдПрдХ рддреЗрдЬ рдзрд╛рд░рд╛рд╡рд╛рд╣рд┐рдХ рдирд╣реАрдВ рджреЗрдЦрд╛ рд╣реИред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЗрд╕ рджреГрд╖реНрдЯрд┐рдХреЛрдг рдХреЛ Roslyn.Emit рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рдЬреЛ рдПрдХрддрд╛ рдФрд░ AOT рдкрд░рд┐рджреГрд╢реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХрджрдо рд╕рд╣реА рд╣реИред

Source: https://habr.com/ru/post/hi455952/


All Articles