2011-02-28 53 views
8
綁定靜態方法/函數來Func鍵 財產

我正在使用XAML創建一個對象樹和節點之一是這樣的:在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> 

我想知道是否有綁定方法/函數的函數功能性的快速簡便的方法,我談論的方法在這裏執行的方法/函數的不是值。 (我能想到的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> 

感謝您提前給予任何幫助,並對壞的英語語法感到抱歉,這不是我的母語:)

回答

5

我可以考慮一些方法使它看起來更乾淨,但沒有一個綁定的語法問。我猜你會最滿意的將是writing your own markup extension,所以你可以使它看起來像{d:StaticMethod Program.Method1},但你一定要使用反射,但它將是緩存微不足道,並會看起來比值轉換器更好。

5

謝謝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 
}