Задача: Утилиты
Исходник: Парсер, генератор классов из asp.net, язык: C# [code #545, hits: 9109]
автор: - [добавлен: 17.12.2007]
  1. // ПРИМЕР
  2. string sourcePage = "";
  3. using (StreamReader sr = new StreamReader(AppDomain.CurrentDomain.BaseDirectory + @"Default.tmpx", Encoding.Default, true, 0x1000))
  4. sourcePage = sr.ReadToEnd();
  5. AspNetGenerator gen = new AspNetGenerator();
  6. CodeCompileUnit ccu = null;
  7. try
  8. {
  9. ccu = gen.CreateCode(sourcePage, @"Default");
  10. }
  11. catch (AspNetGeneratorHostException exc)
  12. {
  13. ....
  14. }
  15.  
  16. ICodeGenerator ics = (new CSharpCodeProvider()).CreateGenerator();
  17. StringWriter sw = new StringWriter();
  18. IndentedTextWriter itw = new IndentedTextWriter(sw);
  19. CodeGeneratorOptions cgo = new CodeGeneratorOptions();
  20. cgo.BlankLinesBetweenMembers = true;
  21. ics.GenerateCodeFromCompileUnit(ccu, itw, cgo);
  22.  
  23. textBox1.Text = sw.ToString();
  24.  
  25.  
  26. // AspNetGenerator CLASS
  27. using System;
  28. using System.CodeDom;
  29. using System.IO;
  30. using System.Reflection;
  31. using System.Web;
  32. using System.Web.Hosting;
  33.  
  34.  
  35. namespace XXX.AspNetGenerator
  36. {
  37. public class AspNetGenerator
  38. {
  39. private const string APP_NAME = @"XXX ASP.NET Generator";
  40. private const string DOMAIN_NAME = APP_NAME + @" domain";
  41. private const string TEMP_DIRECTORY = APP_NAME;
  42. internal const string FAKE_ASPX_FILE = @"fake.aspx";
  43.  
  44. public AspNetGenerator()
  45. {}
  46.  
  47. public CodeCompileUnit CreateCode(string templateText, string pragmaFileName)
  48. {
  49. return GeneratorHost().CreateCode(templateText, pragmaFileName);
  50. }
  51.  
  52. private AspNetGeneratorHost GeneratorHost()
  53. {
  54. string appPath = AppDomain.CurrentDomain.BaseDirectory;
  55. CreateFakeAspxFile(appPath);
  56.  
  57. AppDomainSetup setup = new AppDomainSetup();
  58. setup.PrivateBinPath = "";
  59. setup.PrivateBinPathProbe = "*";
  60. setup.ShadowCopyFiles = "true";
  61. setup.ApplicationBase = (new Uri(appPath, true)).ToString();
  62. setup.ApplicationName = APP_NAME;
  63. Assembly entryAssembly = Assembly.GetEntryAssembly();
  64. setup.DisallowCodeDownload = true;
  65.  
  66. AppDomain dom = AppDomain.CreateDomain(DOMAIN_NAME, null, setup);
  67. dom.SetData(".appPath", appPath);
  68. dom.SetData(".appDomain", "*");
  69. dom.SetData(".appVPath", "/");
  70. dom.SetData(".domainId", dom.FriendlyName);
  71. dom.SetData(".hostingVirtualPath", "/");
  72. dom.SetData(".hostingInstallDir", HttpRuntime.AspInstallDirectory);
  73.  
  74. MethodInfo mi = typeof(ApplicationHost).GetMethod("InitConfigInNewAppDomain", BindingFlags.Static | BindingFlags.NonPublic);
  75. mi.Invoke(null, BindingFlags.Static | BindingFlags.NonPublic, null, new object[]{dom}, null);
  76.  
  77.  
  78. return (AspNetGeneratorHost)dom.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, typeof(AspNetGeneratorHost).FullName);
  79. }
  80.  
  81. private FileInfo CreateFakeAspxFile(string appPath)
  82. {
  83. if (null == _fakeAspxFile)
  84. {
  85. _fakeAspxFile = new FileInfo(appPath + AspNetGenerator.FAKE_ASPX_FILE);
  86. if (!_fakeAspxFile.Exists)
  87. {
  88. using (StreamWriter sw = _fakeAspxFile.CreateText())
  89. {
  90. sw.Write(@"");
  91. sw.Flush();
  92. }
  93. }
  94. }
  95. return _fakeAspxFile;
  96. }
  97.  
  98. private FileInfo _fakeAspxFile;
  99. }
  100. }
  101.  
  102. // AspNetGeneratorHost CLASS
  103. using System;
  104. using System.IO;
  105. using System.Web;
  106. using System.Web.Hosting;
  107. using System.Web.UI;
  108. using System.Reflection;
  109. using System.CodeDom;
  110.  
  111. namespace XXX.AspNetGenerator
  112. {
  113.  
  114. internal class AspNetGeneratorHost: MarshalByRefObject
  115. {
  116. public AspNetGeneratorHost(): base()
  117. {}
  118.  
  119. internal CodeCompileUnit CreateCode(string templateText, string pragmaFileName)
  120. {
  121. CodeCompileUnit unit = null;
  122. try
  123. {
  124. unit = CreateCompileUnit(Parse(templateText, pragmaFileName));
  125. }
  126. catch (Exception exc)
  127. {
  128. if (null == exc.InnerException) throw new AspNetGeneratorHostException(exc);
  129. throw new AspNetGeneratorHostException(exc, new AspNetGeneratorHostException(exc.InnerException));
  130. }
  131. finally
  132. {
  133. HttpRuntime.UnloadAppDomain();
  134. }
  135. return unit;
  136. }
  137.  
  138. protected internal PageParser Parse(string templateText, string pragmaFileName)
  139. {
  140. // Формирование "поддельного" http контекста
  141. StringWriter writer = new StringWriter();
  142. HttpWorkerRequest request = new SimpleWorkerRequest(AspNetGenerator.FAKE_ASPX_FILE, null, writer);
  143. HttpContext context = new HttpContext(request);
  144.  
  145. // Создаем, настраиваем парсер и парсируем
  146. PageParser parser = new PageParser();
  147. SetNotPublicProperty(typeof(BaseParser), "Context", parser, context);
  148. SetNotPublicField(typeof(TemplateParser), "_lineNumber", parser, 1);
  149. SetNotPublicField(typeof(TemplateParser), "_fIgnoreNextSpaceString", parser, true);
  150. SetNotPublicField(typeof(TemplateParser), "_currentPragmaFile", parser, pragmaFileName);
  151. InvokeNotPublicMethod(typeof(TemplateParser), "PrepareParse", parser, new object[]{});
  152. InvokeNotPublicMethod(typeof(TemplateParser), "ParseStringInternal", parser, new object[]{templateText});
  153.  
  154. return parser;
  155. }
  156.  
  157. protected internal CodeCompileUnit CreateCompileUnit(PageParser parser)
  158. {
  159. // Создаем компайлер и необходимый для его работы ресур-билдер
  160. object pageCompiler = Activator.CreateInstance(WebCompilation.GetType("System.Web.Compilation.PageCompiler"),
  161. BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, null, new object[]{parser}, null);
  162. object stringResourceBuilder = Activator.CreateInstance(WebCompilation.GetType("System.Web.StringResourceBuilder"),
  163. BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance, null, new object[]{}, null);
  164.  
  165. // Инициализируем компайлер
  166. Type typeBaseCompiler = WebCompilation.GetType("System.Web.Compilation.BaseCompiler");
  167. SetNotPublicField(typeBaseCompiler, "_stringResourceBuilder", pageCompiler, stringResourceBuilder);
  168.  
  169. // Создаем codeDom
  170. InvokeNotPublicMethod(typeBaseCompiler, "BuildSourceDataTree", pageCompiler, new object[]{});
  171.  
  172. return (CodeCompileUnit)GetNotPublicField(typeBaseCompiler, "_sourceData", pageCompiler);
  173. }
  174.  
  175. protected internal Assembly WebCompilation
  176. {
  177. get
  178. {
  179. if (null == _webCompilation)
  180. {
  181. // Ищем среди всех сборок домена сборку System.Web.dll
  182. Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
  183. foreach(Assembly a in assemblies)
  184. if (@"System.Web" == a.GetName().Name)
  185. {
  186. _webCompilation = a;
  187. break;
  188. }
  189. if (null == _webCompilation)
  190. throw new AspNetGeneratorHostException("Can't to find the assembly 'System.Web' in current application domain.");
  191. }
  192. return _webCompilation;
  193. }
  194. }
  195.  
  196. protected internal Assembly _webCompilation;
  197.  
  198. protected internal void SetNotPublicProperty(Type type, string propertyName, object targetObject, object value)
  199. {
  200. PropertyInfo pi = type.GetProperty(propertyName, BindingFlags.Instance | BindingFlags.NonPublic);
  201. pi.SetValue(targetObject, value, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetProperty, null, null, null);
  202. }
  203.  
  204. protected internal void SetNotPublicField(Type type, string fieldName, object targetObject, object value)
  205. {
  206. FieldInfo fi = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
  207. fi.SetValue(targetObject, value, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetProperty, null, null);
  208. }
  209.  
  210. protected internal object GetNotPublicField(Type type, string fieldName, object targetObject)
  211. {
  212. FieldInfo fi = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
  213. return fi.GetValue(targetObject);
  214. }
  215.  
  216. protected internal void InvokeNotPublicMethod(Type type, string methodName, object targetObject, object[] args)
  217. {
  218. MethodInfo mi = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.NonPublic);
  219. mi.Invoke(targetObject, BindingFlags.Instance | BindingFlags.NonPublic, null, args, null);
  220. }
  221.  
  222. }
  223. }
  224.  
  225. // AspNetGeneratorHostException CLASS
  226. using System;
  227. using System.Runtime.Serialization;
  228.  
  229. namespace XXX.AspNetGenerator
  230. {
  231. [Serializable]
  232. public class AspNetGeneratorHostException: Exception
  233. {
  234. protected AspNetGeneratorHostException(SerializationInfo info, StreamingContext context): base(info, context)
  235. {
  236. _innerCallStack = info.GetString("_innerCallStack");
  237. _originalExceptionType = info.GetString("_originalExceptionType");
  238. }
  239.  
  240. public override void GetObjectData(SerializationInfo info, StreamingContext context)
  241. {
  242. base.GetObjectData(info, context);
  243. info.AddValue("_innerCallStack", _innerCallStack);
  244. info.AddValue("_originalExceptionType", _originalExceptionType);
  245. }
  246.  
  247. public AspNetGeneratorHostException(string message): base(message)
  248. {
  249. }
  250.  
  251. public AspNetGeneratorHostException(Exception localException): this(localException.Message)
  252. {
  253. Init(localException);
  254. }
  255.  
  256. public AspNetGeneratorHostException(Exception localException, Exception innerException): base(localException.Message, innerException)
  257. {
  258. Init(localException);
  259. }
  260.  
  261. private void Init(Exception exception)
  262. {
  263. _innerCallStack = exception.StackTrace;
  264. _originalExceptionType = exception.GetType().FullName;
  265. }
  266.  
  267. public string InnerCallStack
  268. {
  269. get { return _innerCallStack ; }
  270. }
  271.  
  272. private string _innerCallStack = "";
  273.  
  274. public string OriginalExceptionType
  275. {
  276. get { return _originalExceptionType ; }
  277. }
  278.  
  279. private string _originalExceptionType = "" ;
  280. }
  281. }
  282.  
Захотелось попользовать парсер и генератор классов из файлов aspx (ascx).
Получилось следующее

Источник: http://rsdn.ru/forum/Message.aspx?mid=866992&only=1

+добавить реализацию