Партия, дай порулить
От: IT Россия linq2db.com
Дата: 07.02.06 02:33
Оценка:
Навеяно Nemerle рулит! :)
Автор: VladD2
Дата: 02.02.06


Интересный получился топик и довольно познавательный. Сразу видно, что за дело профессионально взялись розовые береты
В связи с этим у меня к вам, господа нимерлисты (или как вас теперь ), имеется вопрос.

Вывод типов и прочая функциональщина — это всё очень здорово, это упрощает жизнь, делает код проще, читабельнее, декларативнее. Без всего этого жить скучно, не интересно, но можно, и в в борьбе за всеобщую декларативность меня эти вещи, конечно же, интересуют, но вопрос мой не о них. Меня в данный момент интересуют не локальные проявления декларативности, а то, чем можно эффективно бить по площадям — макросы.

К сожалению, у многих из нас не хватает времени не только на то, чтобы что-то пощупать своими руками, но даже на то, чтобы просто успевать читать форумы RSDN и следить за последними веяниями в индустрии. По-этому, прежде чем самому засучить рукава, уповаую на вас

Суть вопроса. Как я уже сказал выше, меня интересуют прежде всего возможности языка по генерации кода. Вот что я могу сегодня делать на C# с помощью подручных средств. Возьмём, например, такой класс:

public abstract class Test : EditableObject
{
  public abstract int    ID   { get; set; }
  public abstract string Name { get; set; }
}

Этого объявления вполне достаточно, чтобы run-time генератор BLToolkit создал на основании его примерно вот такой код:

namespace EditableObjects.EditableObjectTest.BLToolkitExtension
{
    using BLToolkit.EditableObjects;
    using BLToolkit.Reflection;
    using BLToolkit.TypeBuilder;
    using EditableObjects;
    using System;
    using System.Collections;
    using System.Reflection;

    public class Test : EditableObjectTest.Test, IEditable, IMemberwiseEditable, IPrintDebugState
    {
        // Fields
        private EditableValue<int>    _ID;
        private EditableValue<string> _name;
                
        private static PropertyInfo _ID_$propertyInfo;
        private static PropertyInfo _name_$propertyInfo;

        // Methods
        static Test()
        {
            _ID_$propertyInfo   = TypeHelper.GetPropertyInfo(typeof(EditableObjectTest.Test), "ID",   typeof(int),    Type.EmptyTypes);
            _name_$propertyInfo = TypeHelper.GetPropertyInfo(typeof(EditableObjectTest.Test), "Name", typeof(string), Type.EmptyTypes);
        }

        public Test()
        {
            this._name = new EditableValue<string>("");
        }

        public Test(InitContext)
        {
            this._name = new EditableValue<string>("");
        }

        public override int ID
        {
            get { return this._ID.Value; }
            set
            {
                this._ID.Value = value;
                ((IPropertyChanged)this).OnPropertyChanged(_ID_$propertyInfo);
            }
        }

        public override string Name
        {
            get { return this._name.get_Value(); }
            set
            {
                this._name.set_Value((string) value);
                ((IPropertyChanged)this).OnPropertyChanged(_name_$propertyInfo);
            }
        }

        void IEditable.AcceptChanges()
        {
            this._ID.AcceptChanges();
            this._name.AcceptChanges();
        }

        bool IEditable.IsDirty
        {
            get
            {    
                bool flag1 = this._ID.IsDirty;
                        
                if (!flag1)
                    flag1 = this._name.IsDirty;

                return flag1;
            }
        }

        void IEditable.RejectChanges()
        {
            this._ID.RejectChanges();
            this._name.RejectChanges();
        }

        bool IMemberwiseEditable.AcceptMemberChanges(PropertyInfo propertyInfo, string memberName)
        {
            bool flag1 = this._ID.AcceptMemberChanges(_ID_$propertyInfo, memberName);

            if (!flag1)
                flag1 = this._name.AcceptMemberChanges(_name_$propertyInfo, memberName);

            return flag1;
        }

        void IMemberwiseEditable.GetDirtyMembers(PropertyInfo propertyInfo, ArrayList list)
        {
            this._ID.  GetDirtyMembers(_ID_$propertyInfo,   list);
            this._name.GetDirtyMembers(_name_$propertyInfo, list);
        }

        bool IMemberwiseEditable.IsDirtyMember(PropertyInfo propertyInfo, string memberName, ref bool isDirty)
        {
            bool flag1 = this._ID.IsDirtyMember(_ID_$propertyInfo, memberName, ref isDirty);

            if (!flag1)
                flag1 = this._name.IsDirtyMember(_name_$propertyInfo, memberName, ref isDirty);

            return flag1;
        }

        bool IMemberwiseEditable.RejectMemberChanges(PropertyInfo propertyInfo, string memberName)
        {
            bool flag1 = this._ID.RejectMemberChanges(_ID_$propertyInfo, memberName);

            if (!flag1)
                flag1 = this._name.RejectMemberChanges(_name_$propertyInfo, memberName);

            return flag1;
        }

        void IPrintDebugState.PrintDebugState(PropertyInfo propertyInfo, ref string str)
        {
            this._ID.  PrintDebugState(_ID_$propertyInfo,   ref str);
            this._name.PrintDebugState(_name_$propertyInfo, ref str);
        }
    }
}

Т.е. мы имеем следующие вещи:

1. Внутренную реализацию свойств как EditableValue<int> и EditableValue<string>.
2. Реализацию интерфейса IEditable, включая методы AcceptChanges, RejectChanges и флаг IsDirty.
3. Генерацию события OnPropertyChanged при изменении свойств.
4. Ещё кое-что по мелочи.

Естественно, всё это дело не захардкожено. Генератор берёт информацию о том что и где генерировать из атрибутов, которыми по уши обвешан базовый класс EditableObject. В результате мы имеем почти 100% декларацию и, как результат, минимум работы.

Вопрос. Можно ли достичь подобного уровня декларативности на Nemerle?

Если это принципиально возможно, то не исключено, что в BLToolkit в скором времени может появится соответствующая поддержка
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.