2017-08-03 70 views
0

我已經訂閱了一些方法,一個事件,並希望通過特定的順序,我給他們,像這樣調用它們:調用順序由特定的屬性

foreach (var method in LOAD_DEPENDENCIES.GetInvocationList() 
     .OrderBy(x => x.Method.GetCustomAttributes(typeof(InvocationOrderAttribute),false))) 
{ 
    method.DynamicInvoke(localStats, this); 
} 

其中(當然)事件是LOAD_DEPENDENCIES和屬性是InvocationOrderAttibute注意foreach的身體工作,參數DynamicInvoke不是問題。

該屬性看起來像這樣:

public class InvocationOrderAttribute : Attribute , IComparable 
{ 
    public int order; 
    public InvocationOrderAttribute(int order) 
    { 
     this.order = order; 
    } 

    public int CompareTo(object obj) 
    { 
     return this.order.CompareTo((obj as InvocationOrderAttribute).order); 
    } 
} 

我實現了IComparable希望OrderBy將用它來確定順序。

這是行不通的,通過調試我檢查到我從來沒有進入該循環體的那個foreach循環。 ALL訂閱的方法具有該屬性。

問題是,我在做什麼錯在foreach循環的LINQ查詢或屬性?

編輯:

它不是最好的,但工作原理:

foreach (var method in LOAD_DEPENDENCIES.GetInvocationList() 
     .OrderBy(y => y.Method.GetCustomAttributes(false) 
     .OfType<InvocationOrderAttribute>().FirstOrDefault().order)) 
{ 
    method.DynamicInvoke(localStats, this); 
} 

回答

1

.GetCustomAttributes返回一個object[],所以.OrderBy將使用Comparer<object[]>.Default,因爲它要使用,將在你拋出異常一些IComparable執行類型object[],它不存在。

相反,您應該使用.GetCustomAttribute<InvocationOrderAttribute>,它返回屬性,如果不存在這樣的屬性,則返回null。沒有屬性的方法與那些具有屬性的方法比較如何?

剛剛寫了一個小例子,它不使用事件處理函數,也不使用事件處理函數,而事件處理函數不攜帶該屬性,後者在排序中位於前者的前面。該示例中的代表類型爲Action(您的是其他內容)。

編輯:C#4.0中能夠版本不CustomAttributeExtensions

屬性:

[AttributeUsage(AttributeTargets.Method)] 
public sealed class InvocationOrderAttribute : Attribute 
{ 
    public int Order { get; private set; } 

    public InvocationOrderAttribute(int order) 
    { 
     Order = order; 
    } 
} 

新:有用的方法對所有類型的事件

/// <summary> 
/// Get individual handlers of the invocation list of the specified <paramref name="@event"/>, 
/// ordered by the <see cref="InvocationOrderAttribute"/> of the handler's method. 
/// </summary> 
/// <typeparam name="TDelegate">Delegate type of the <paramref name="@event"/>.</typeparam> 
/// <exception cref="ArgumentException"><typeparamref name="TDelegate"/> is not a delegate type.</exception> 
/// <remarks>Handlers without the attribute come last.</remarks> 
public static IEnumerable<TDelegate> OrderedInvocationList<TDelegate>(TDelegate @event) 
{ 
    if (!typeof(Delegate).IsAssignableFrom(typeof(TDelegate))) 
     throw new ArgumentException(typeof(TDelegate) + " is not a delegate type."); 

    if (@event == null) // empty invocation list 
     return Enumerable.Empty<TDelegate>(); 

    return ((Delegate)(object)@event).GetInvocationList() 
     .Select(handler => 
     { 
      var attribute = (InvocationOrderAttribute)handler.Method.GetCustomAttributes(typeof(InvocationOrderAttribute), false).FirstOrDefault(); 
      return new 
      { 
       Handler = (TDelegate)(object)handler, 
       Order = attribute != null ? attribute.Order : int.MaxValue 
      }; 
     }) 
     .OrderBy(ho => ho.Order) 
     .Select(ho => ho.Handler); 
} 

用法:

public static class Program 
{ 
    private static event Action Event; 

    private static void RaiseEvent() 
    { 
     foreach (var h in MyAwesomeCode.OrderedInvocationList(Event)) 
      h(); 
    } 

    [InvocationOrder(1)] 
    private static void M1() { Console.WriteLine("M1"); } 

    [InvocationOrder(2)] 
    private static void M2() { Console.WriteLine("M2"); } 

    private static void M3() { Console.WriteLine("M3"); } 

    public static void Main() 
    { 
     RaiseEvent(); // works on empty invocation list 

     Event += M3; 
     Event += M2; 
     Event += M1; 
     Event += M3; 
     Event += M2; 
     Event += M1; 

     RaiseEvent(); // works with methods not carrying the attribute 
    } 
} 

輸出:M1 M1 M2,M2,M3 M3

在你的代碼的改進(包括第2溶液):

  • 沒有NullReferenceException如果沒有登記處理。
  • NullReferenceException如果某個處理程序沒有屬性。
  • 在排序過程中不反映屬性。
  • 適用於所有事件委託類型。
  • 沒有.DynamicIvoke(醜,不重構友好,效率低下)
  • (不調用委託的「方法」,使用的標識符標準外殼)
+0

謝謝您的回答。 我使用這個Unity和版本C#4,我沒有'GetCustomAttribute <>'(可能不是因爲版本,但我沒有)。在這種情況下可以採取什麼解決方法? – agiro

+1

'.GetCustomAttributes()。OfType ()。FirstOrDefault()'是等效的 – tinudu

+0

沒有運氣:/仍然沒有做我想做的事。 – agiro