(495) 925-0049, ITShop интернет-магазин 229-0436, Учебный Центр 925-0049
  Главная страница Карта сайта Контакты
Поиск
Вход
Регистрация
Рассылки сайта
 
 
 
 
 

ASP.Net Expression Builders. Редактор своего типа выражений. Часть 2

Источник: andir-notes

Продолжим играться с "построителями выражений" в ASP.Net.

Напомню, что существует три выражения поставляемые по умолчанию вместе с ASP.Net:

<system.web>

    <compilation>

        <expressionBuilders>

            <add expressionPrefix="Resources"

                 type="System.Web.Compilation.ResourceExpressionBuilder"/>

            <add expressionPrefix="ConnectionStrings"

                 type="System.Web.Compilation.ConnectionStringsExpressionBuilder"/>

            <add expressionPrefix="AppSettings"

                 type="System.Web.Compilation.AppSettingsExpressionBuilder"/>

        </expressionBuilders>

    </compilation>

</system.web>

Для каждого из них существует некоторый редактор, который позволяет устанавливать значения свойств в Design-Time.

Рассмотрим нашу небольшую страничку:

default.aspx

<%@ Page Language="C#" AutoEventWireup="true"

    CodeBehind="Default.aspx.cs" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"

    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head runat="server">

    <title>ASP.Net Expression Builder Test</title>

</head>

<body>

    <h1>ASP.Net Expression Builder Test</h1>

    <table class=borderall cellpadding="3" cellspacing="0">

        <col style="color: DarkGreen" align="left" />

        <tr>

            <th>$AppSettings</th>

            <td>

                <asp:Label ID="appSettingsLabel" runat="server"

                           Text='<%$ AppSettings: MyAppSetting %>' />

            </td>

        </tr>

        <tr>

            <th>$ConnectionStrings</th>

            <td>

                <asp:Label ID="connectionStringsLabel" runat="server"

                           Text='<%$ ConnectionStrings: MyConnectionString %>' />

            </td>

        </tr>

        <tr>

            <th>$Resources</th>

            <td>

                <asp:Label ID="resourcesLabel" runat="server"

                           Text='<%$ Resources: MyResources, MyResourceKey %>' />

            </td>

        </tr>

    </table>

</body>

</html>

Переключаемся в просмотр дизайна:

Скриншот: default.aspx в режиме Дизайн

Выбираем произвольный серверный контрол (на скриншоте у меня выбран первый appSettingsLabel) и смотрим в окно Properties.

Скриншот: Окно свойств в Design-Time

Вещи, на которые стоит обратить внимание я выделил. Первое, это маленький квадратик возле свойства Text - если к нему подвести мышь, то появиться подсказка "Property is expression bound.". Второе, это секция Data и её элемент (Expressions). Именно в нём и скрыт редактор, который позволяет присваивать различным свойствам элемента значения параметрам выражения.

Скриншот: Редактор для связывания построителей со свойствами элемента управления 

"Bindable properties" показывает список доступных свойств элемента управления к которым можно "прибиндить" выражение.

В выпадающем списке "Expression type" можно выбрать любой ExpressionBuilder зарегистрированный в web.config.

Теперь самое интересное. В окне "Expression properties" можно увидеть стандартный грид с набором свойств (да, на скриншоте видно только одно свойство, но если выбрать Resources среди типов, то там будет уже два). Этот грид является "редактором" для выбранного типа выражения. И для своего типа выражения можно реализовать свой редактор.

Делается это с помощью атрибута ExpressionEditorAttribute, наследника ExpressionEditor (который находиться в System.Design.dll) и наследника ExpressionEditorSheet.

Реализация редактора свойств для выражения

В качестве выражения я буду использовать простенькое выражение HashItExpression. Синтаксис выдумаем следующим:

<%$ HashIt: MD5("строка, хеш которой я хочу получить") : Base64 %>

Параметрами моего выражения будут служить:

  • Алгоритм хэширования (MD5, SHA1, SHA256, SHA512),
  • Текст в кавычках, который надо захешировать,
  • Кодировка в которой следует вывести получившийся набор байт (Base64 или Hex - строка в шестнадцатеричном представлений).

Вначале реализуем набор структур и функций, которые делают разбор выражения и вычисляют его значение.

HashItEvaluator.cs

using System;

using System.Linq;

using System.Security.Cryptography;

using System.Text;

using System.Text.RegularExpressions;

 

namespace Home.Andir.Examples

{

    public enum HashAlg

    {

        MD5,

        SHA1,

        SHA256,

        SHA512

    }

 

    public enum EncodeType

    {

        Base64,

        Hex

    }

 

    public static class HashItEvaluator

    {

        public class HashItParseResults

        {

            public HashAlg HashAlg { get; set; }

            public string Source { get; set; }

            public EncodeType EncodeType { get; set; }

        }

 

        public static string Eval(string expression)

        {

            var parseResults = ParseExpression(expression);

            if (parseResults != null)

            {

                return Eval(parseResults);

            }

 

            return "Invalid expression";

        }

 

        private static string Eval(HashItParseResults parseResults)

        {

            HashAlgorithm hash = CreateAlgorithm(parseResults.HashAlg);

 

            var result = hash.ComputeHash(

                Encoding.Default.GetBytes(parseResults.Source));

 

            if (parseResults.EncodeType == EncodeType.Hex)

            {

                return String.Concat(

                    result.Select(x => String.Format("{0:x2}", x)).ToArray()

                    );

            }

 

            return Convert.ToBase64String(result);

        }

 

        private static HashAlgorithm CreateAlgorithm(HashAlg alg)

        {

            switch (alg)

            {

                case HashAlg.MD5: return MD5.Create();

                case HashAlg.SHA1: return new SHA1Managed();

                case HashAlg.SHA256: return new SHA256Managed();

                case HashAlg.SHA512: return new SHA512Managed();

            }

 

            throw new ArgumentOutOfRangeException("alg");

        }

 

        public static HashItParseResults ParseExpression(string expression)

        {

            // expression == MD5(source) [: Base64]

            Regex expRe = new Regex(

                @"(?<alg>MD5/SHA1/SHA256/SHA512)\('(?<source>.+)'\)(\s*:\s*(?<enc>(Base64/Hex)))?",

                RegexOptions.IgnoreCase

                );

 

            var match = expRe.Match(expression);

 

            if (match != null)

            {

                string alg = match.Groups["alg"].Value;

                string source = match.Groups["source"].Value;

                string enc = match.Groups["enc"].Value;

 

                return new HashItParseResults()

                {

                    HashAlg = (HashAlg)Enum.Parse(typeof(HashAlg), alg, true),

                    Source = source,

                    EncodeType = enc.ToUpper() == "BASE64" ? EncodeType.Base64 : EncodeType.Hex

                };

            }

 

            return null;

        }

    }

}

Метод HashItEvaluator. ParseExpression   пытается распарсить выражение с помощью регулярных выражений и если ему это удаётся, то возвращает структуру с результатами.

Метод HashItEvaluator. Eval используя результаты парсинга, вычисляет выражение (то есть хеширует строчку и полученный результат представляет в текстовом виде).

Ну а теперь можно и реализовать сам ExpressionBuilder и его редактор. Следите за руками.

HashItExpressionBuilder.cs

using System.CodeDom;

using System.Web.Compilation;

using System.Web.UI;

 

namespace Home.Andir.Examples

{

    [ExpressionEditor(typeof(HashItExpressionEditor))]

    public class HashItExpressionBuilder : ExpressionBuilder

    {

        public override CodeExpression GetCodeExpression(

            BoundPropertyEntry entry,

            object parsedData,

            ExpressionBuilderContext context)

        {

            return new CodePrimitiveExpression(

                HashItEvaluator.Eval(entry.Expression));

        }

    }

}

Обращаем внимание на атрибут установленный у класса.

HashItExpressionEditor.cs

using System;

using System.Web.UI.Design;

 

namespace Home.Andir.Examples

{

    public class HashItExpressionEditor : ExpressionEditor

    {

        public override object EvaluateExpression(

            string expression,

            object parseTimeData,

            Type propertyType,

            IServiceProvider serviceProvider)

        {

            return HashItEvaluator.Eval(expression);

        }

 

        public override ExpressionEditorSheet GetExpressionEditorSheet(

            string expression,

            IServiceProvider serviceProvider)

        {

            return new HashItExpressionEditorSheet(expression, serviceProvider);

        }

    }

}

У редактора надо реализовать две функции: EvaluateExpression - вычисляющий выражение и GetExpressionEditorSheet - возвращающий источник для редактора свойств (тот самый грид!).

HashItExpressionEditorSheet.cs

using System;

using System.ComponentModel;

using System.Web.UI.Design;

 

namespace Home.Andir.Examples

{

    public class HashItExpressionEditorSheet : ExpressionEditorSheet

    {

        public HashItExpressionEditorSheet(

            string expression,

            IServiceProvider serviceProvider

            ) : base(serviceProvider)

        {

            var parseResults = HashItEvaluator.ParseExpression(expression);

            if (parseResults != null)

            {

                HashAlg = parseResults.HashAlg;

                EncodeType = parseResults.EncodeType;

                Source = parseResults.Source;

            }

        }

 

        [DefaultValue(HashAlg.MD5), DisplayName("Hash algorithm")]

        public HashAlg HashAlg { get; set; }

        [DefaultValue(EncodeType.Hex), DisplayName("Result encoding")]

        public EncodeType EncodeType { get; set; }

        [DefaultValue(""), DisplayName("Some text")]

        public string Source { get; set; }

 

        public override bool IsValid

        {

            get { return true; }

        }

 

        public override string GetExpression()

        {

            var result = String.Format("{0}('{1}')", HashAlg.ToString(), Source);

 

            if (EncodeType == EncodeType.Base64)

                result += ": Base64";

 

            return result;

        }

    }

}

Итак, тут три свойства, которые и определяют параметры моего выражения.

Тестируем.

Примечание: Чтобы студия подгрузила новый зарегистрированный редактор для выражения, нужно скомпилировать проект и студию перезапустить.

Регистрируем новое выражение в web.config

<?xml version="1.0"?>

<configuration>

    <system.web>

        <compilation debug="true">

            <expressionBuilders>

                <add expressionPrefix="HashIt"

                     type="Home.Andir.Examples.HashItExpressionBuilder"

                     />

            </expressionBuilders>

        </compilation>

    </system.web>

</configuration>

Создаём тестовую страничку:

HashItExpression.aspx

<%@ Page Language="C#" %>

<html xmlns="http://www.w3.org/1999/xhtml">

<head runat="server">

    <title>ASP.Net HashIt Expression Builder Test</title>

</head>

<body>

    <h1>ASP.Net HashIt Expression Builder Test</h1>

    <table class=borderall cellpadding="3" cellspacing="0">

        <col style="color: DarkGreen" align="left" />

        <tr>

            <th>

                <span>$HashItExpression</span>

            </th>

            <td>

                <asp:Label ID="hashItLabel" runat="server"

                           Text="<%$ HashIt:MD5('Строка'): Base64 %>" />

            </td>

        </tr>

    </table>

</body>

</html>

И открываем её в режиме Design:

Скриншот: Тестовая страница с выражением в Design-Time

Выбираем элемент управления hashItLabel и открываем диалог для биндинга выражений:

Скриншот: Диалог биндинга выражений к свойствам элемента управленияКак видно на скриншоте, появился тип выражения "HashIt" и в редакторе свойств появились все свойства этого выражения. Отлично!

Ссылки по теме

Файлы для загрузки


 Распечатать »
 Правила публикации »
  Написать редактору 
 Рекомендовать » Дата публикации: 15.02.2010 
 

Магазин программного обеспечения   WWW.ITSHOP.RU
Microsoft 365 Business Standard (corporate)
Microsoft Office 365 Персональный 32-bit/x64. 1 ПК/MAC + 1 Планшет + 1 Телефон. Все языки. Подписка на 1 год.
Microsoft Windows Professional 10, Электронный ключ
Microsoft 365 Apps for business (corporate)
Microsoft 365 Business Basic (corporate)
 
Другие предложения...
 
Курсы обучения   WWW.ITSHOP.RU
 
Другие предложения...
 
Магазин сертификационных экзаменов   WWW.ITSHOP.RU
 
Другие предложения...
 
3D Принтеры | 3D Печать   WWW.ITSHOP.RU
 
Другие предложения...
 
Новости по теме
 
Рассылки Subscribe.ru
Информационные технологии: CASE, RAD, ERP, OLAP
Безопасность компьютерных сетей и защита информации
Новости ITShop.ru - ПО, книги, документация, курсы обучения
Программирование на Microsoft Access
CASE-технологии
Программирование на Visual Basic/Visual Studio и ASP/ASP.NET
Компьютерная библиотека: книги, статьи, полезные ссылки
 
Статьи по теме
 
Новинки каталога Download
 
Исходники
 
Документация
 
 



    
rambler's top100 Rambler's Top100