I currently have a WPF project that makes use of MVVM. In my project, I make use of a static class which acts as a cache for collections used by the various controls in my app, something like this:
public static class AppCache
{
public static ObservableCollection<MyObject> MyObjects { get; set; }
private static async void GetMyObjectsAsync()
{
await Task.Run(() => GetMyObjects());
Mediator.Instance.NotifyColleagues("MyObjectsUpdatedMessage", true); // A helper class that implements messaging
}
private static GetMyObjects()
{
// Get objects via service call
...
MyObjects = result;
}
static AppCache()
{
MyObjects = new ObservableCollection<MyObject>();
GetMyObjectsAsync();
}
}
I then subscribe to the mediator in my various viewmodels:
public class MyViewModel : ViewModelBase
{
...
public ObservableCollection<MyObject> MyObjects
{
// My ViewModelBase lets me implement INotifyPropertyChanged like this
get { return GetValue(() => MyObjects); }
set { SetValue(() => MyObjects, value); }
}
[Message("MyObjectsUpdatedMessage")]
private void OnMyObjectSourceUpdated(bool c)
{
MyObjects = AppCache.MyObjects;
}
public MyViewModel ()
{
Mediator.Instance.RegisterHandler<bool>("MyObjectsUpdatedMessage", OnMyObjectSourceUpdated);
}
}
The problem I have with this method is that when I do things with the collections in the ViewModels (eg. add or edit a MyObject) I then have to go back and manually update the global AppCache collection and make sure it matches up with what is in the ViewModel, then make sure that I update all of the other ViewModels using this collection to use the new value since there is no binding involved: MyOtherViewModel.MyObjects = AppCache.MyObjects
The alternative is to make GetMyObjectsAsync() public and have the AppCache update itself from the database after I make changes from my ViewModel, then use the Mediator to update all the other views using the collection. I don't like this either as it means I end up making a service call I don't want to.
What I'm trying to figure out is if there is any way to use Reactive Extensions to simplify my process, such that I can have some kind of Reactive Property defined in the AppCache which my ViewModels subscribe to, and which when updated will push its updates out to all the ViewModels, something of a mix between the two options available to me (Manually update the AppShared collection but then have all its subs notified without needing the mediator).
I suppose really what I want is to have a property that is essentially bindable and shareable between ViewModels.
Is there any kind of Reactive Property I can use to achieve this sort of thing? Something like:
EDIT:
I was able to get the subscription to work as follows, but this is again similar to the option of using the Mediator as I have to call NotifyMyObjectChanged whenever I update MyObjects. Is there a way to make MyObjectsObservable 'listen' for changes to MyObjects and automatically call NotifyMyObjectChanged? If there isn't a way to do this, is there a benefit to using RX for this over the Mediator?
public static class AppCache
{
public static ObservableCollection<MyObject> MyObjects { get; set; }
public static IObservable<ObservableCollection<MyObject>> MyObjectsObservable => _mySubject; // C# 6 syntax
public static Subject<ObservableCollection<MyObject>> _mySubject { get; set; }
private static async void GetMyObjectsAsync()
{
await Task.Run(() => GetMyObjects());
NotifyMyObjectChanged() // this basically just replaces the mediator
}
private static GetMyObjects()
{
...
MyObjects = result;
}
private static void NotifyMyObjectChanged()
{
_mySubject.OnNext(MyObjects);
}
static AppCache()
{
_mySubject = new Subject<ObservableCollection<MyObject>>();
GetMyObjectsAsync();
}
}
public class MyViewModel : ViewModelBase
{
ObservableCollection<MyObject> MyObjects
{
get { return GetValue(() => MyObjects); }
set { SetValue(() => MyObjects, value); }
}
IDisposable _subscription { get; }
MyViewModel()
{
_subscription = AppCache.MyObjectsObservable.Subscribe (HandleMyObjectChanged);
}
private void HandleMyObjectChanged(ObservableCollection<MyObject> myObjects)
{
MyObjects = myObjects;
}
public void Dispose()
{
_subscription.Dispose();
}
}
So what you want to do is something like this:
public static class AppCache
{
static AppCache()
{
_mySubject = new Subject<MyObject>();
}
private static void NotifyMyObjectChanged(MyObject object)
{
_mySubject.OnNext(object);
}
public static IObservable<MyObject> MyObjectsObservable
{
get { return _mySubject; }
}
}
public class MyViewModel : ViewModelBase
{
MyViewModel()
{
_subscription = AppCache.MyObjectsObservable.
.Where(x => x == value)
.Subscribe (HandleMyObjectChanged);
}
private void HandleMyObjectChanged(MyObject object)
{
... do work here ....
}
public void Dispose()
{
_subscription.Dispose();
}
}
In this case what you're basically doing here is sending a notification to your view model that something on your MyObject has changed. You can take the object variable from the handler and use that to copy the changed properties into your view model. Alternatively you could send a "message" class that has a list of properties and their new values, that might be a little lighter than sending the entire object.
The other thing to keep in mind is that the Observable might send the "event" on a thread other than the UI thread. There's a Subscribe override that lets you specific a TaskScheduler to use, so you can specify the UI scheduler so you don't have to do the marshalling yourself.
As I said in my comment, there are tons of ways to do this, so you'll have to play around to find something that fits your needs the best, but hopefully this gives you some direction.
UPDATE
So here's a bit of an update to your AppCache code (from your edit), but your question is basically that you want to get rid of the mediator and replace it with RX. In the end, you still end up with a mediator of some sort, you just have to decide whether RX gives you something more than your own implementation of a mediate would. I would (and do) use RX, but it's really a preference thing, so you're going to have to do some research on your own.
This shows you the use of the Observable.FromEventPattern function, which is pretty useful and gives you a nice shortcut:
public static class AppCache
{
ObservableCollection<MyObject> MyObjects { get; set; }
public static IObservable<ObservableCollection<MyObject>> MyObjectsObservable { get; private set; }
private static async void GetMyObjectsAsync()
{
await Task.Run(() => GetMyObjects());
NotifyMyObjectChanged() // this basically just replaces the mediator
}
private static GetMyObjects()
{
...
MyObjects = result;
MyObjectsObservable = Observable.FromEventPattern(h=>MyObjects.CollectionChanged += h, h=>MyObjects.CollectionChanged -= h);
}
static AppCache()
{
GetMyObjectsAsync();
}
}
I wanted to show you the usuage but this code isn't perfect, if a subscriber calls Subscribe before the MyObjectsObservable is created, obviously it would blow up.
Here's another link that shows you a lot of the stuff that RX can do, that to me makes it a great tool: http://www.introtorx.com/uat/content/v1.0.10621.0/04_CreatingObservableSequences.html#
Related
I'm referencing a class that performs various demanding operations using callbacks rather than async operations. For example:
class CallbackClass : SomeSdkCallbacks
{
public void RequestData()
{
// We call this to request some data.
// After some time, this will trigger OnDataReturned to be called
}
public void OnDataReturned(DataObject data)
{
// This will be called automatically with returned data via SomeSdkCallbacks
}
}
There are many instances of this type of structure throughout this class.
What I'm trying to do is create a wrapper class around this one that simplifies it's usage. The structure that I'm going for at the moment is:
class MyWrapperClass
{
CallbackClass CallbackClass;
public MyWrapperClass()
{
this.CallbackClass = new CallbackClass();
}
public DataObject GetData()
{
this.CallbackClass.RequestData();
// Somehow wait until this.CallbackClass.OnDataReturned is called?
// Somehow get the data that would be passed in to this.CallbackClass.OnDataReturned()???
}
}
What is the best method of wrapping up a 'callback' architecture into a single asynchronous method?
Edit: To clarify, ideally I would like to package this up into a single method that can return the data in a single request. See the MyWrapperClass.GetData() method in my example for my ideal structure.
Edit 2: I'm aware that this desired architecture is bad form. Unfortunately that is the requested structure that has been asked of me.
I think this is what you want:
class CallbackClass<T>
{
private TaskCompletionSource<T> task = new TaskCompletionSource<T>();
public void RequestData()
{
}
public void OnDataReturned(T data)
{
task.SetResult(data);
}
public Task<T> Task { get { return task.Task; } }
}
class MyWrapperClass
{
public Task<DataObject> GetData()
{
var cls = new CallbackClass<DataObject>();
cls.RequestData();
return cls.Task;
}
}
Just note that TaskCompletionSource must be created per operation so you don't use the same one for two different calls. With this you can use the async keyword. This might help a bit more.
In your situation you can add some event on CallBackClass.
Like here:
class CallbackClass : SomeSdkCallbacks
{
public event Action<object> DataReturnedEvent;
public void RequestData()
{
// We call this to request some data.
// After some time, this will trigger OnDataReturned to be called
}
public void OnDataReturned(DataObject data)
{
DataReturnedEvent?.Invoke(data);
}
}
And you can use the event in the wrapper class
class MyWrapperClass
{
CallbackClass CallbackClass;
public MyWrapperClass()
{
this.CallbackClass = new CallbackClass();
CallbackClass.DataReturnedEvent =+ ProcessData;
}
private void ProcessData(object Data)
{
//some data processing
}
public DataObject GetData()
{
this.CallbackClass.RequestData()
}
}
I am working on a C# project and I need to manage a local cache of data and present it on a GUI.
For example I have:
public class DataFromOtherLibrary
Now I want make a class to help translate the information I need out of it
public class MyDataModel
{
private DataFromOtherLibrary cache;
public MyDataModel ( DataFromOtherLibrary Source)
{
cache = Source;
}
public long Field1 { get { return cache.SomeField; } }
public long Field2 { get { return cache.OtherFiled; } }
}
Now the issue I have is I need to create a MyDataModel for every DataFromOtherLibrary it would be nice to have a single translator class. I'm not sure how to do it and still implement properties (which I need to data-bind to).
Thanks
Matt
You should use a Provider with all your DataModels in it Like:
public class MyDataModelProvider
{
public List<MyDataModel> DataModelList { get; set; }
MyDataModelProvider()
{
loadDataModelList();
}
private void LoadDataModel()
{
foreach (Cachobject c in Cache)
{
this.DataModelList.Add(new MyDataModel(c.valueA,c.valueB));
}
}
}
and for this Provider you also need a Factory Like:
[Singleton(true)]
public class DataModelListProviderFactory
{
private static DataModelListProvider dataListProvider;
public DataModelListProvider getInstance()
{
if (dataListProvider == null)
{
dataListProvider = new DataModelListProvider();
return dataListProvider;
}
else
return dataListProvider;
}
}
Because now you have a single Spot with all your DataModels and you only must recieve them once. You can also easily search the List for a specific Model if you have a case or you show all the Data in a View.
You can read here more about Factory Patterns.
Hope that helps.
How can I use C# generics to avoid having to create an extension function like so for each and every auto-generated class (Linq to SQL DBML)?
static public CharacterViewModel ToViewModel(this Character c)
{
return new CharacterViewModel(c);
}
Having a function like this provides a fairly clean way of selecting a set of items from the DB as their corresponding ViewModel, like so:
var characters = new ObservableCollection<CharacterViewModel>(from p in DB.Characters
select p.ToViewModel());
I'd like to see something like:
static public T ToViewModel<T,K>(K dbmlClass)
{
return new T(dbmlClass);
}
But I have a feeling this will involve Reflection-style object generation and I don't know how efficient that would be (or how to accomplish it).
By the way, I did previously investigate operator overloading the assignment ('=') as a possible solution, which could provide implicit casting, but I believe this would require overloading the = in the auto-generated class which I am not able to do.
Update
Thanks all, for the answers. I think I have a few avenues to check out now. To provide a bit more context, as some mentioned it wasn't clear. All of my ViewModels are derived from the following:
public class BaseDO<T>: BaseDO
{
public BaseDO(T model)
{
Model = model;
}
public T Model { get; set; }
}
abstract public class BaseDO: INotifyPropertyChanged, INotifyDeleted
{
#region Standard INotifyPropertyChanged Implementation
public void NotifyPropertyChanged(string propertyName)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged = (o, e) => { };
#endregion
public event EventHandler OnEntityDeleted = (o, e) => { };
public void NotifyEntityDeleted()
{
OnEntityDeleted(this, new EventArgs());
}
}
public interface INotifyDeleted
{
event EventHandler OnEntityDeleted;
void NotifyEntityDeleted();
}
You could use a library such as Automapper. With this you have 1 place where you setup the configuration of how objects are mapped. You can then have:
public static T ToViewModel<T,K>(K dbmlClass)
{
return AutoMapper.Mapper.Map<T>(dbmlClass);
}
// Register mappings
public static void ConfigureMappings()
{
AutoMapper.Mapper.CreateMap<Character, CharacterViewModel>();
}
It's not really clear from your question whether you want to generate the view model classes automatically or whether you've already written them and each one accepts the model as a constructor parameter. If the former then I personally add INPC to the model classes using either Castle Proxy or Frody. If the latter then I believe this is what you're after:
public static class Helper
{
static public T ToViewModel<T>(this object dbmlClass)
{
return (T)Activator.CreateInstance(typeof(T), dbmlClass);
}
}
Which you would then use like this:
var model = new Model();
var view_model = model.ToViewModel<ViewModel>();
Maybe overloading a method is not exactly what is necessary but this is the best i could come up with.
I have a class:
public class Worker {
private string jobType;
public Worker(string jt)
{
this.jobType = jt;
}
public void ProcessJob()
{
if(jobType.Equals("Pizza") MakePizza();
else if (jobType.Equals("Burger") MakeBurger();
}
private void MakePizza()
{
// make pizza
}
private void MakeBurger()
{
// make burger
}
}
The above is just an example of illustration. When the class is constructed, it is constructed with a specific job type, and that won't change. However it may need to perform millions of jobs, always of the same type. The ProcessJob() will be called all the time, but the caller won't know what type of worker this is. I would like to avoid running the if check every single time, there has to be a way to do that check only once and prep it.
In my case, making child classes (pizza worker, burger worker, etc.) is not an option, as in my real case, the class is large and there is only one tiny difference. Changing it will impact the whole architecture so it needs to be avoided.
Create an abstract base class, which contains common things a worker can do. Then declare derived classes for specialized workers.
public abstract class Worker
{
public abstract void ProcessJob();
}
public class PizzaWorker : Worker
{
public override void ProcessJob()
{
// Make pizza
}
}
public class BurgerWorker : Worker
{
public override void ProcessJob()
{
// Make burger
}
}
Now you can create workers of different types and let them do their job:
var workers = new List<Worker>();
workers.Add(new PizzaWorker());
workers.Add(new BurgerWorker());
foreach (Worker worker in workers) {
woker.ProcessJob();
}
This will automatically call the right implementation of ProcessJob for each type of worker.
Note: If-else-if cascades and switch statements are often an indication that the code works in a procedural rather than object-oriented way. Refactor it to be object-oriented!
You could use a delegate created when the object is constructed, this way the dispatch is done automatically:
public class Worker
{
private delegate void MakeSomething();
private MakeSomething makeWhat;
private string jobType;
public Worker(string jt)
{
this.jobType = jt;
switch (jt)
{
case "Pizza":
makeWhat = new MakeSomething(MakePizza);
break;
case "Burger":
makeWhat = new MakeSomething(MakeBurger);
break;
default:
throw new ArgumentException();
}
}
public void ProcessJob()
{
makeWhat();
}
private void MakePizza()
{
//make pizza
}
private void MakeBurger()
{
//make burger
}
}
I would still recommend to use sub classes. If you cannot inherit from Worker then create new class hierarchy that is used inside the worker. This way anyone using Worker class doesn't have to know that there are sub classes. If you really really hate sub classes or you have some other reason you don't want them you can use dictionary. It contains job type as key and Action as the method it calls. If you need more jobs just create the private method and register it in the RegisterWorkers method.
private Dictionary<string, Action> actions = new Dictionary<string, Action>();
public Worker(string jt)
{
this.jobType = jt;
this.RegisterWorkers();
}
private void RegisterWorkers
{
this.actions["Pizza"] = this.MakePizza;
this.actions["Burger"] = this.MakeBurger;
}
public void ProcessJob()
{
var action = this.actions[this.jobType];
action();
}
No, I don't think it should be avoided. Any common functionality should go in a base class. I think you need a static factory method, that returns a child class based on the string parameter.
public abstract class Worker {
public virtual void ProcessJob();
public static Worker GetWorker(string jobType) {
if(jobType.Equals("Pizza")
return new PizzaWorker();
else if (jobType.Equals("Burger")
return new BurgerWorker();
else
throw new ArgumentException();
}
// Other common functionality
protected int getFoo() {
return 42;
}
}
public class PizzaWorker : Worker {
public override void ProcessJob() {
// Make pizza
int y = getFoo() / 2;
}
}
public class BurgerWorker : Worker {
public override void ProcessJob() {
// Make burger
int x = getFoo();
}
}
So to use this:
Worker w = Worker.GetWorker("Pizza");
w.ProcessJob(); // A pizza is made.
This is exactly why there are patterns: Command, Strategy, Decorator.
I believe the command pattern is what you are looking for. First you have a basic 'command' template:
public interface IJob {
void ProcessJob();
}
Different jobs would then be performed as follows:
public class MakePizza : IJob {
// implement the interface
public void ProcessJob() {
// make a pizza
}
}
Now, you could have a JobFactory as follows:
public static class JobFactory {
public static IJob GetJob(string jobType) {
if(jobType.Equals("Pizza"){
return new MakePizza();
} else (jobType.Equals("Burger") {
return new MakeBurger();
}
// to add jobs, extend this if-else-if or convert to switch-case
}
}
Worker can now look like this:
public class Worker {
private IJob job;
public Worker(string jt) {
job = JobFactory.GetJob(jt);
}
public void ProcessJob() {
job.ProcessJob();
}
}
If you don't have access to code to make these changes, then another pattern you may want to look into is the Adapter.
You're talking about basic inheritance here. There are a couple of ways that you could do this.
Make a Base Class that is
public class Job
{
virtual void ProcessJob();
}
Then a MakePizza class
public class MakePizza : Job
{
public void ProcessJob()
{
//make Pizza
}
}
Then in your worker class instead of having a JobType as a string which will lead to all kinds of potential bugs.
public class Worker{
private Job jobType;
public Worker(Job jt){
this.jobType = jt;
}
public void ProcessJob()
{
Job.ProcessJob();
}
}
If you have to pass through a string you could simply load up the JobType through reflection, throwing a error if the type doesn't exist.
having to change other classes means you need to change code, not that you need to change architecture. the best answer is just to change the code. in the long term, the maintenance burden of having to write this in a less-than-ideal fashion will cost you more than just changing the code. use inheritance and bite the bullet on making the change now. if you have iterators that will have problems with dealing with subtypes, your iterators are doing more than being iterators, and you are better off fixing that than going forward with them. if the other classes care about what subtype of worker they are dealing with, that's a problem in and of itself that you should fix. ultimately, the dependent code should not care which type of worker it is. that's really what you are after anyway. the instance of a type that has work as its base type is still a worker and that is all the class using a worker should care about.
Is there a way to watch an object graph for changes on any object, and do something based on that change?
Lets say I have the following:
public class Main:INotifyPropertyChanged
{
public ObservableCollection<Foo> FooItems { get; }
public ObservableCollection<Bar> BarItems { get; }
}
public class Foo:INotifyPropertyChanged
public class Bar:INotifyPropertyChanged
{
public ObservableCollection<Other> OtherItems { get; }
}
public class Other:INotifyPropertyChanged
What would be the best way to implement some sort of change notification system across all objects? For example an autosave, where any change would trigger the system to serialize the Main class.
Should I have glue code in the Main class watching the BarItems for changes, hooking up to their PropertyChanged? This seems a bit messy, and error prone to me. Is there a better way?
Rather than objects raising their own property changed events, perhaps they could raise a shared event instead. For example:
public class SharedChangeNotifier
{
public static event EventHandler<DataChangedEventArgs> SharedChangeEvent;
protected void RaiseChangeEvent()
{
if (SharedChangeNotifier.SharedChangeEvent != null)
{
SharedChangeNotifier.SharedChangeEvent(
this, new DataChangedEventArgs());
}
}
}
public class Foo : SharedChangeNotifier
{
public int MyProperty
{
get { ... }
set
{
...
RaiseChangeEvent();
}
}
}
You could then attach an event handler to the static SharedChangeNotifier's SharedChangeEvent to be notified whenever any object deriving from SharedChangeNotifier is changed, like this:
SharedChangeNotifier.SharedChangeEvent += (sender, args) => {
DoWhatever();
};
I just read an interesting blog post on that issue at http://www.lennybacon.com/ReBlinderFleckChangeTracking.aspx
The post is in German, but as it's mostly code, it should be OK.
Hope this helps!
The way I have done it in the past was to create a separate ChangeTracker class with a method to Register objects into it. Inside that method, use reflection to explore the registered object, and hook into events on each of its properties that implements INotifyPropertyChanged.
You can then add methods to the ChangeTracker to interrogate the state, e.g. IsDirty(), or even implement INotifyPropertyChanged on the ChangeTracker.
(Be sure to implement and use IDisposable on the ChangeTracker, and drop all the event handlers at that time).
You could have the same handler for all items that implement INotifyPropertyChanged events:
foreach (INotifyPropertyChanged obj in FooItems)
obj.PropertyChanged+= this.modified;
// likewise for bar items, and when items are added
private void modified(object sender, EventArgs args)
{
this.Save();
}
edit> To do the same when an item is added:
private void addToList<T>(ref List<T> l, T item) where T : INotifyPropertyChanged
{
item.PropertyChanged += this.modified;
l.Add(item);
}
call it using:
Foo item = new Foo();
List<Foo> fooItems = new List<Foo>();
addToList<Foo>(ref fooItems, item);