Навеяно
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>>