Анонимная функция / Закрытие вопроса

Позвольте мне представить свой подход под названием Yappi . Он относится к генераторам производного класса Runtime proxy, добавляя новые функции к существующему объекту или типу, например Dynamic Proxy от Caste Project.

Он позволяет реализовать INotifyPropertyChanged один раз в базовом классе, а затем объявлять производные классы в следующих стиль, поддерживающий INotifyPropertyChanged для новых свойств:

public class Animal:Concept
{
    protected Animal(){}
    public virtual string Name { get; set; }
    public virtual int Age { get; set; }
}

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

var animal = Concept.Create.New();

И вся работа по реализации INotifyPropertyChanged может сделайте это следующим образом:

public class Concept:INotifyPropertyChanged
{
    //Hide constructor
    protected Concept(){}

    public static class Create where TConcept:Concept
    {
        //Construct derived Type calling PropertyProxy.ConstructType
        public static readonly Type Type = PropertyProxy.ConstructType>(new Type[0], true);
        //Create constructing delegate calling Constructor.Compile
        public static Func New = Constructor.Compile>(Type);
    }


    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(PropertyChangedEventArgs eventArgs)
    {
        var caller = PropertyChanged;
        if(caller!=null)
        {
            caller(this, eventArgs);
        }
    }

    //define implementation
    public class Implementation : DefaultImplementation where TConcept:Concept
    {
        public override Func OverrideGetter(PropertyInfo property)
        {
            return PropertyImplementation.GetGetter(property.Name);
        }
        /// 
        /// Overriding property setter implementation.
        /// 
        /// Base type for implementation. TBaseType must be TConcept, and inherits all its constraints. Also TBaseType is TDeclaringType.
        /// Type, declaring property.
        /// Constructed type. TConstructedType is TDeclaringType and TBaseType.
        /// Type of property.
        /// PropertyInfo of property.
        /// Delegate, corresponding to property setter implementation.
        public override Action OverrideSetter(PropertyInfo property)
        {
            //This code called once for each declared property on derived type's initialization.
            //EventArgs instance is shared between all events for each concrete property.
            var eventArgs = new PropertyChangedEventArgs(property.Name);
            //get delegates for base calls.
            Action setter = PropertyImplementation.GetSetter(property.Name);
            Func getter = PropertyImplementation.GetGetter(property.Name);

            var comparer = EqualityComparer.Default;

            return (pthis, value) =>
            {//This code executes each time property setter is called.
                if (comparer.Equals(value, getter(pthis))) return;
                //base. call
                setter(pthis, value);
                //Directly accessing Concept's protected method.
                pthis.OnPropertyChanged(eventArgs);
            };
        }
    }
}

Он полностью безопасен для рефакторинга, не использует отражения после построения типа и достаточно быстро.

0
задан martineau 7 March 2019 в 09:22
поделиться

1 ответ

Как вы добавляете любую переменную экземпляра, self.func = func:

class Objective():
    def __init__(self, function):
        if isinstance(function, str):
            def func(x): # no need for self
               return eval(function, locals())
            self.func = func # here

        elif callable(function):
            self.func = function

    def __call__(self, x):
        return self.func(x)

Обратите внимание, вам не нужно self в вашем определении func. Также обратите внимание, что вы нигде не использовали анонимную функцию. Вы использовали нормальное определение функции.

Наконец, (хотя вы, вероятно, не должны этого делать), вам нужно получить x в пространствах имен, доступных для eval, так что-то вроде:

return eval(function, locals())
0
ответ дан juanpa.arrivillaga 7 March 2019 в 09:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: