Мне просто нужно было сделать то же самое. Вот мое решение (хотя, возможно, не самый лучший, но, по крайней мере, довольно элегантный):
Во-первых, создайте интерфейс для всех ваших сущностей для реализации, который наследуется от INotifyPropertyChanging. Это используется для подключения некоторых методов расширения и обеспечения отличной реализации нашей реализации. В моем случае интерфейс называется ISandboxObject:
public interface ISandboxObject : INotifyPropertyChanging
{
// This is just a marker interface for Extension Methods
}
Затем создайте новый статический класс, который будет содержать метод расширения для получения DataContext. Это достигается путем поиска обработчика событий в LINQ Change Tracker, прикрепленном к событию INotifyPropertyChanging.PropertyChanging. Как только мы нашли трекер изменений, мы можем получить DataContext оттуда:
/// <summary>
/// Obtain the DataContext providing this entity
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static DataContext GetContext(this ISandboxObject obj)
{
FieldInfo fEvent = obj.GetType().GetField("PropertyChanging", BindingFlags.NonPublic | BindingFlags.Instance);
MulticastDelegate dEvent = (MulticastDelegate)fEvent.GetValue(obj);
Delegate[] onChangingHandlers = dEvent.GetInvocationList();
// Obtain the ChangeTracker
foreach (Delegate handler in onChangingHandlers)
{
if (handler.Target.GetType().Name == "StandardChangeTracker")
{
// Obtain the 'services' private field of the 'tracker'
object tracker = handler.Target;
object services = tracker.GetType().GetField("services", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(tracker);
// Get the Context
DataContext context = services.GetType().GetProperty("Context").GetValue(services, null) as DataContext;
return context;
}
}
// Not found
throw new Exception("Error reflecting object");
}
Теперь у вас есть хороший метод расширения, который предоставит вам DataContext из любого объекта, реализующего ISandboxObject. Пожалуйста, добавьте еще несколько проверок на ошибки, прежде чем использовать их в гневе!