Reputation: 1891
I have a common library that need to be shared among my main WPF app and its plugins... In the common library I have a BaseViewModel with this code
public Dispatcher RootDispatcher
{
get
{
_rootDispatcher = _rootDispatcher ??
(App.Current != null
? App.Current.Dispatcher
: Dispatcher.CurrentDispatcher);
return _rootDispatcher;
}
// unit tests can get access to this via InternalsVisibleTo
internal set
{
_rootDispatcher = value;
}
}
protected void TriggerSafeEvent(EventHandler eve, EventArgs args)
{
if (RootDispatcher.CheckAccess())
{
if (eve != null)
eve.Invoke(this, args);
}
else
{
RootDispatcher.Invoke((Action)delegate()
{
if (eve != null)
eve.Invoke(this, args);
});
}
}
So the consumer ViewModel could call an event in a way like this without to be worried wherever thread belongs from the main thread:
MyViewModel : BaseViewModel {
..
TriggerSafeEvent(MyEventHandler, MyEventArgs);
}
Since the common library is not a WPF application, the App object is not resolved.
I think that this approach could be wrong, however I feel that is not an uncommon practice to share often call methods within a base view model.
What is the best solution to handle with App object?
Upvotes: 1
Views: 365
Reputation: 37059
Use dependency injection. This is off the top of my head but it'll work.
public interface IDispatcherProvider {
Dispatcher Dispatcher { get; }
}
BaseViewModel
public static IDispatcherProvider DispatcherProvider { get; set; }
Interface implementation:
public class DispatcherProviderImplementation : IDispatcherProvider
{
public DispatcherProviderImplementation(Func<Dispatcher> getDispatcher)
{
_getDispatcher = getDispatcher;
}
private Func<Dispatcher> _getDispatcher;
public virtual Dispatcher Dispatcher => _getDispatcher?.Invoke();
// If your compiler won't accept the above, try this
/*
public virtual Dispatcher Dispatcher {
get {
return (_getDispatcher == null) ? null : _getDispatcher();
}
}
*/
}
App
static App()
{
BaseViewModel.DispatcherProvider
= new DispatcherProviderImplementation(() => (App.Current != null
? App.Current.Dispatcher
: Dispatcher.CurrentDispatcher));
}
Upvotes: 2