Привязка статического метода / функции к свойству Func <T>в XAML - PullRequest
8 голосов
/ 28 февраля 2011

Я работаю над использованием XAML для создания дерева объектов, и один из узлов выглядит следующим образом:

public class ExecuteMethod : INode
{
    #region Implementation of INode

    public bool Evaluate()
    {
        return Function != null && Function();
    }

    public string Name { get; set; }

    private string _type;
    public string Type
    {
        get
        {
            if (string.IsNullOrEmpty(_type))
            {
                _type = GetType().Name;
            }

            return _type;
        }
    }


    #endregion

    public Func<bool> Function { get; set; }

}

Моя цель - сделать как можно более чистый XAML и код, что неВ данный момент я создаю свойства оболочки для каждой функции:

public static Func<bool> Func1 { get { return Method1; } }

public static bool Method1()
{
    //Do stuff here
    return true;
}

, а xaml выглядит так для приведенного выше кода:

<Root 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns="clr-namespace:XamlBT;assembly=XamlBT"  
xmlns:d="clr-namespace:TestBT;assembly=TestBT">
<Root.Child>
    <Sequence Name="sequence1" >
        <ExecuteMethod Name="e1.1" Function="{x:Static d:Program.Func1}" />
        <Selector Name="selector1" >
            <ExecuteMethod Name="e2.1" Function="{x:Static d:Program.Func1}"  />
        </Selector>
    </Sequence>
</Root.Child>

Я хотел бы знать, есть ли быстрый и простой способ привязать методы / функции к свойству Func, я говорю о методе, а не о значении выполняемого метода / функции.(Я могу подумать об использовании некоторой магии отражения в valueConverter или внутри узла / класса ExecuteMethod, но это просто грязно и странно) Пример того, как я хотел бы, чтобы XAML выглядел:

<Root 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns="clr-namespace:XamlBT;assembly=XamlBT"  
xmlns:d="clr-namespace:TestBT;assembly=TestBT">
<Root.Child>
    <Sequence Name="sequence1" >
        <ExecuteMethod Name="e1.1" Function="{x:Static d:Program.Method1}" />
        <Selector Name="selector1" >
            <ExecuteMethod Name="e2.1" Function="{x:Static d:Program.Method1}"  />
        </Selector>
    </Sequence>
</Root.Child>

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

Ответы [ 2 ]

6 голосов
/ 01 марта 2011

Спасибо, jbtule!

вот решение, если кто-то захочет:

[MarkupExtensionReturnType(typeof (Func<bool>))]
public class StaticMethodExtension : MarkupExtension
{
    public StaticMethodExtension(string method)
    {
        Method = method;
    }
     [ConstructorArgument("method")]
    public string Method { get; set; }

    private Func<bool> _func;

    #region Overrides of MarkupExtension

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        if (_func == null)
        {
            int index = Method.IndexOf('.');
            if (index < 0)
            {
                throw new ArgumentException("MarkupExtensionBadStatic");
            }
            string qualifiedTypeName = this.Method.Substring(0, index);
            if (qualifiedTypeName == string.Empty)
            {
                throw new ArgumentException("MarkupExtensionBadStatic");
            }
            IXamlTypeResolver service = serviceProvider.GetService(typeof(IXamlTypeResolver)) as IXamlTypeResolver;
            if (service == null)
            {
                throw new ArgumentException("MarkupExtensionNoContext");
            }
            var memberType = service.Resolve(qualifiedTypeName);
            var str = this.Method.Substring(index + 1, (this.Method.Length - index) - 1);

            if (str == string.Empty)
            {
                throw new ArgumentException("MarkupExtensionBadStatic");
            }

            var reflectedFunc = memberType.GetMethod(str,
                                                     BindingFlags.FlattenHierarchy | BindingFlags.Public |
                                                     BindingFlags.Static);

            if (reflectedFunc != null)
            {
                if (reflectedFunc.ReturnType == typeof(bool))
                {
                    var v = Delegate.CreateDelegate(typeof(Func<bool>), reflectedFunc, true);

                    _func = (Func<bool>) v;
                }

            }

        }

        return _func;
    }

    #endregion
}
5 голосов
/ 01 марта 2011

Я могу придумать несколько способов сделать его более чистым, но нет синтаксиса для того, что вы просите.Я предполагаю, что вы бы больше всего были довольны написанием написания собственного расширения разметки , чтобы вы могли сделать его похожим на {d:StaticMethod Program.Method1}, но вам определенно придется использовать отражение, но это будет тривиальнокэша и будет выглядеть лучше, чем конвертер значений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...