Zippy.NET фреймворк

Архитектура

Основу приложениия составляет класс, унаследованный от ZippyNet.WebApplication , который обеспечивает жизненный цикл приложения.
Аналогично PHP решению, необходимо метод getTemplate для загрузки шаблонов страниц а также можно переопределить метод Route для реализации ЧПУ.


namespace TestApp
{                
    public class Application : ZippyNet.WebApplication
    {
        public Application() : base()
        {
        }

        override protected string getHomePage()
        {
            //возвращает имя класса домашней страницы
            return "TestApp.Pages.Main";
        }

        override protected void Route(string URL)
        {
        }

        override public string getTemplate(string pagename)
        {
            pagename = pagename.Replace("TestApp.Pages.", "").Replace(".", "\\");
            string filePath = HttpContext.Current.Server.MapPath("~\\Template\\Pages\\") + pagename + ".html";
            if(!File.Exists(filePath)) throw new Exception(filePath + " is not exists");

            return  File.ReadAllText(filePath, System.Text.Encoding.UTF8);
        }
    }
    }
Экземпляр класса Application создается и стартует в файле global.asax.cs после каждого HTTP запроса

  
    public class RouteHandler : IRouteHandler
    {
        public IHttpHandler GetHttpHandler(RequestContext requestContext)
        {
            return new HttpHandler();
        }
    }
    public class HttpHandler : IHttpHandler, IRequiresSessionState
    {
        public void ProcessRequest(HttpContext context)
        {
            try
            {
                new TestApp.Application().Run();
            }
            catch (Exception) { }
  
        }
          
        public bool IsReusable
        {
            get { return false; }
        }
    }
    public class Application : global::System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            RouteTable.Routes.Add("test", new Route("", new RouteHandler()));
        }
        void Application_Error(Object sender, EventArgs e)
        {
            
        }
        protected void Session_Start()
        {
             
        }
    }    
    
Собственно, это все что нужно для создания проекта приложения. Далее работа приложения принципиально не отличается от работы PHP варианта.

Особенности

В силу типизированности языка С# имеется ряд особенностей по сравнению с PHP решением.

Замыкания в обработчиках

Поскольку в C# полноценные лямбда-функции, короткие обработчики можно реализовывать прямо в конструкторе при создании элемента.


                Label label1 = new Label("label1");
                ClickLink link1 = new ClickLink("link1");
                link1.onClick((HtmlComponent sender) =>
                {
                    label1.text="I am clicked";
                });
                add(label1);
                add(link1);
                
Компонент, на который есть ссылка в обработчимке, очевидно должен быть обьявлен раньше.
Более громоздкие обработчики можно разместить отдельно.

                ...
                   ClickLink link1 = new ClickLink("link1");
                   link1.onClick(this.Click);
                }
                private void Click(HtmlComponent sender){
                   
                }
                

Обращение к компонентам

Поскольку в C# нет динамических свойств как в PHP, при обращении к компоненту требуется приведение типа.


                    private void Click(HtmlComponent sender){
                       ((Label)this._c("label1")).text = "I am clicked";
                    }
                
Такая конструкция выглядит несколько громоздко поскольку функция _c возвращает тип HtmlComponent. Более компактный вариант через функци, возвращающую dynamic.

                    private void Click(HtmlComponent sender){
                       this._cd("label1").text = I am clicked";
                    }
                
Такая запись требует аккуратности иначе возникнет ошибка в runtime.
Еще один вариант - если к компоненту есть множество обращений в разных обработчиках, он может быть обьявлен полем класса страницы (и страница и компоненты- обычные классы)

                   
                   public class Page1
                   {  
      
                    private Label label1; = new Label("la bel1");
                    
                    public Page1()
                    {                
                       this.label1 = new Label("label1");
                       add(this.label1) ;  
                    } 
                    ...     
                    private void Click(HtmlComponent sender){
                       this.label1.text = "I am clicked";
                    }
                    ...