2012-12-27 48 views
0

有沒有辦法讓開放泛型類型參數的委託實例像這樣?從System.Type中創建一個通用委託實例

Action<T> SomethingHappened; 

編譯器給我一個錯誤。

我可能每兩年就會問這個問題而被遺忘。我找不到以前的類似問題,所以我無論如何都在問。

什麼我真的想要做的是這樣的:

在實體框架,我想,只要一些新行添加到表或表中的現有行一些數據被修改,我想寫一個通用的發佈商框架,可以告訴任何感興趣的聽衆,發生這樣或那樣的事情。

例如,發佈者可以告知所有有興趣知道表格的客戶表中的新增行或者客戶表中的任何修改的所有聆聽者。

的聽衆可能是記錄器,電子郵件發件人等

目前,我在做什麼是一個雜牌,但我想更類型安全的解決方案。下面是我目前在做什麼:

public partial class DaEntities : ObjectContext 
    { 
     Action<object, ObjectStateEntry> EntityModified; 
     Action<object, ObjectStateEntry> EntityDeleted; 
     Action<object, ObjectStateEntry> EntityAdded; 

    public override int SaveChanges(SaveOptions options) 
     { 
      var modifiedEntities = 
       ObjectStateManager.GetObjectStateEntries(
       System.Data.EntityState.Added | System.Data.EntityState.Modified); 

      var deletedEntities = 
       ObjectStateManager.GetObjectStateEntries(
       System.Data.EntityState.Deleted); 

      foreach (var entry in modifiedEntities) 
      { 
       var type = GetObjectType(entry.GetType()); 

       // fire delegates here 
      } 

      return base.SaveChanges(options); 
     } 
    } 

在上述情況下,我寧願希望有這樣的事情:

public static Action<T, ObjectStateEntry> EntityModified; 
public static Action<T, ObjectStateEntry> EntityDeleted; 
public static Action<T, ObjectStateEntry> EntityAdded; 

,並讓它們指向一個通用的方法,像這樣:

public void SomethingHappenedToAnEntity<T, ObjectStateEntry> 
    (T t, ObjectStateEntry e) 
{ 
    // do stuff here 
} 
+0

的問題是,你不」 t知道哪些類型可能會改變(因爲從調用ObjectStateManager.GetObjectStateEntries返回的類型在編譯時調用是未知的),所以當你調用這個方法時,即使你能夠改變簽名來接受'Action '參數,你也不能爲'T'提供適當的類型。 – jam40jeff

回答

0

有一個未定義的'T'沒有任何意義... - 你真正想要的是一個自定義事件參數。你將不得不迫使你的類型是在一些具體的點 - 所以,你可以傳遞參數,如:

Action<object> SomethingHappened; 

然後在消費方法的代碼分支...

或者,你可以欺騙,讓動態調度試圖找出的類型,你(在一個小的性能成本) - 但這只是推動解決該問題...

void Main() 
{ 
    dynamic objectToProcess = new Moop(); 

    DoStuff(objectToProcess); //Dynamic dispatch will pick the best match automatically 
} 

public void DoStuff(Moop obj) 
{ 
    Console.WriteLine(obj.GetType()); 
} 

public void DoStuff(Gloop obj) 
{ 
    Console.WriteLine(obj.GetType()); 
} 

public void DoStuff(Bloop obj) 
{ 
    Console.WriteLine(obj.GetType()); 
} 

public class Moop {} 
public class Gloop {} 
public class Bloop {}