I have a question which is an extension of the following question raised on this site.
Is there a more elegant way to merge observables when return type is unimportant?
I have an IObservable<Unit> (lets say X), a reactive collection (Y) and a property (Z). Return type is not important. I just want to subscribe when any of these change.
I know how to observe all 3 and Subscribe using Observable.Merge as below.
Observable.Merge(X, Y.Changed, ObservableForProperty(Z).Select(_ => Unit.Default)).Subscribe(..)
And it works.
However, when I try to use WhenAny(...,....,....).Subscribe(), the subscribe does not get triggered when my X changes. What is the syntax for doing the above using WhenAny(...) rather than Observable.Merge(..)??
I prefer to use WhenAny(....) because I am using ReactiveUI in other places.
Example:
Say I've got a class derived from ReactiveObject with following properties.
public class AnotherVM : ReactiveObject
{
public bool IsTrue
{
get { return this.isTrue; }
set { this.RaiseAndSetIfChanged(x => x.isTrue, ref this.isTrue, value); }
}
public IObservable<Unit> Data
{
get { return this.data; }
}
public ReactiveCollection MyCol
{
get { return Mycol; }
}
}
public class MyVM : ReactiveObject
{
MyVM
{
// do WhenAny or Observable.Merge here....
}
}
I want to observe the above properties in AnotherVM class using Observable.Merge(..) or WhenAny(...) in MyVM class. I found that I do not always get a notification when I subscribe to the above in MyVM using WhenAny(...) or Merge(...) when either of the 3 properties change.
WhenAny is not for monitoring across sets of arbitrary observables, it's for monitoring the properties of an object supported by ReactiveUI (like a ReactiveObject or reactive collection).
For the general case of combining changes in observable streams, Observable.Merge is the right way to go.
EDIT
I note that you have declared the Data and MyCol properties read only. If you use a Merge like this:
Observerable.Merge(this.WhenAnyValue(o=>o.IsTrue, v=>Unit.Default),
this.Data,
this.MyCol.CollectionChanged.Select(v=>Unit.Default))
...then you must be careful not to change the backing fields. If you do, then you will get missing events - maybe this is what is happening?
In that case you would need to wire up those properties to RaiseAndSetIfChanged and use a Switch to keep track - e.g. if this.data could change then you would need (I'm using ReactiveUI 5 + .NET 4.5 here in case the RaiseAndSetIfChanged syntax looks odd):
public IObservable<Unit> Data
{
get { return this.data; }
private set { this.RaiseAndSetIfChanged(ref data, value); }
}
and your merge would be something like:
Observerable.Merge(this.WhenAnyValue(o=>o.IsTrue, v=>Unit.Default),
this.WhenAnyObservable(x => x.Data),
this.MyCol.CollectionChanged.Select(v=>Unit.Default))
WhenAnyObservable is conceptually equivalent to this:
WhenAny(x => x.Data, vm => vm.Value).Switch()
using Switch to flip over to the latest value of Data when it changes. Don't forget to use the setter to change values of data!
This should do it.
IObservable<Unit> merged =
Observerable.Merge
( this.WhenAnyValue(o=>o.IsTrue, v=>Unit.Default)
, this.Data
, this.MyCol.CollectionChanged.Select(v=>Unit.Default)
)
Theoretically you could write a special version of merge that would disregard the type of the observable and return IObservable<Unit>. Then you could write
IObservable<Unit> merged =
Observerable.MergeToUnit
( this.WhenAnyValue(o=>o.IsTrue)
, this.Data
, this.MyCol.CollectionChanged
)
but then you would need many overloads of MergeToUnit for up to the N parameters you would like to support.
The most general pattern to use with WhenAny with multiple objects is
Observable.CombineLatest
( source0.WhenAnyValue(s=>s.FieldA)
, source1.WhenAnyValue(s=>s.FieldB)
, source2.WhenAnyValue(s=>s.FieldC)
, source3.WhenAnyValue(s=>s.FieldD)
, (a,b,c,d) => Process(a,b,c,d)
)
It's sometimes just better to get used to using the standard combinators.
Related
I'm kind of new to reactive programing and currently working on a spring webflux based application. I'm stuck between few questions.
public class FooServiceImpl {
#Autowired
private FooDao fooDao;
#Autowired
private AService aService;
#Autowired
private BService bService;
public long calculateSomething(long fooId) {
Foo foo = fooDao.findById(fooId); // Blocking call one
if (foo == null) {
foo = new Foo();
}
Long bCount = bService.getCountBByFooId(fooId); // Blocking call two
AEntity aEntity = aService.getAByFooId(fooId); // Blocking call three
// Do some calculation using foo, bCount and aEntity
// ...
// ...
return someResult;
}
}
This is the way we write a blocking code which uses three external API call results (let's consider as DB calls). I'm struggling to convert this into a reactive code, If all three becomes mono and if I subscribe all three will the outer subscriber get blocked?
public Mono<Long> calculateSomething(long fooId) {
return Mono.create(sink -> {
Mono<Foo> monoFoo = fooDao.findById(fooId); // Reactive call one
monoFoo.subscribe(foo -> {
if (foo == null) {
foo = new Foo();
}
Mono<Long> monoCount = bService.getCountBByFooId(fooId); // Reactive call two
monoCount.subscribe(aLong -> {
Mono<AEntity> monoA = aService.getAByFooId(fooId); // Reactive call three
monoA.subscribe(aEntity -> {
//...
//...
sink.success(someResult);
});
});
});
};
}
I saw there is a function called zip, but it only works with two results, So is there a way to apply it here?
Also what will happen if we get subscribe for something inside create method, Will it block the thread?
Would be very thankful if you could help me.
If you gave me the calculation you want you do with those values, it would be easier for me to show the reactor way of doing it. But lets suppose you want to read a value from database and then use that value for another thing. Use flatmaps and make a unique Flux reducing the lines of code and complexity, no need to use subscribe() as told by the other people. Example:
return fooDao.findById(fooId)
.flatmap(foo -> bService.getCountBByFooId(foo))
.flatmap(bCount -> aService.getAByFooId(fooId).getCount()+bCount);
I would like to keep track of how many times a certain key is subscribed to in #ngrx/store. I don't want to have repeated code in each component that subscribes but was hoping to hook into select() somehow. I don't think #effects apply here because I am not looking at dispatched actions.
Does anyone have any ideas on how I would implement this?
Assuming that subscribing to a key means selecting something from the store.
You can try extending the Store with your own service and using that then override the select method with something like:
#Injectable()
class CountingStore<S> extends Store<S> {
public keyCount: {[key:string]: number} = {};
public select = (key: string) => {
keyCount[key] = keyCount[key] ? keyCount[key] + 1 : 1;
return super.select(key);
}
}
I'm trying to understand RxJava and I'm sure this question is a nonsense... I have this code using RxJava:
public Observable<T> getData(int id) {
if (dataAlreadyLoaded()) {
return Observable.create(new Observable.OnSubscribe<T>(){
T data = getDataFromMemory(id);
subscriber.onNext(data);
});
}
return Observable.create(new Observable.OnSubscribe<T>(){
#Override
public void call(Subscriber<? super String> subscriber) {
T data = getDataFromRemoteService(id);
subscriber.onNext(data);
}
});
}
And, for instance, I could use it this way:
Action1<String> action = new Action<String>() {
#Override
public void call(String s) {
//Do something with s
}
};
getData(3).subscribe(action);
and this another with callback that implements Runnable:
public void getData(int id, MyClassRunnable callback) {
if (dataAlreadyLoaded()) {
T data = getDataFromMemory(id);
callback.setData(data);
callback.run();
} else {
T data = getDataFromRemoteService(id);
callback.setData(data);
callback.run();
}
}
And I would use it this way:
getData(3, new MyClassRunnable()); //Do something in run method
Which are the differences? Why is the first one better?
The question is not about the framework itself but the paradigm. I'm trying to understand the use cases of reactive.
I appreciate any help. Thanks.
First of all, your RxJava version is much more complex than it needs to be. Here's a much simpler version:
public Observable<T> getData(int id) {
return Observable.fromCallable(() ->
dataAlreadyLoaded() ? getDataFromMemory(id) : getDataFromRemoteService(id)
);
}
Regardless, the problem you present is so trivial that there is no discernible difference between the two solutions. It's like asking which one is better for assigning integer values - var = var + 1 or var++. In this particular case they are identical, but when using assignment there are many more possibilities (adding values other than one, subtracting, multiplying, dividing, taking into account other variables, etc).
So what is it you can do with reactive? I like the summary on reactivex's website:
Easily create event streams or data streams. For a single piece of data this isn't so important, but when you have a stream of data the paradigm makes a lot more sense.
Compose and transform streams with query-like operators. In your above example there are no operators and a single stream. Operators let you transform data in handy ways, and combining multiple callbacks is much harder than combining multiple Observables.
Subscribe to any observable stream to perform side effects. You're only listening to a single event. Reactive is well-suited for listening to multiple events. It's also great for things like error handling - you can create a long sequence of events, but any errors are forwarded to the eventual subscriber.
Let's look at a more concrete with an example that has more intrigue: validating an email and password. You've got two text fields and a button. You want the button to become enabled once there is a email (let's say .*#.*) and password (of at least 8 characters) entered.
I've got two Observables that represent whatever the user has currently entered into the text fields:
Observable<String> email = /* you figure this out */;
Observable<String> password = /* and this, too */;
For validating each input, I can map the input String to true or false.
Observable<Boolean> validEmail = email.map(str -> str.matches(".*#.*"));
Observable<Boolean> validPw = password.map(str -> str.length() >= 8);
Then I can combine them to determine if I should enable the button or not:
Observable.combineLatest(validEmail, validPw, (b1, b2) -> b1 && b2)
.subscribe(enableButton -> /* enable button based on bool */);
Now, every time the user types something new into either text field, the button's state gets updated. I've setup the logic so that the button just reacts to the state of the text fields.
This simple example doesn't show it all, but it shows how things get a lot more interesting after you get past a simple subscription. Obviously, you can do this without the reactive paradigm, but it's simpler with reactive operators.
I have a domain object which has a collection of primitive values, which represent the primary keys of another domain object ("Person").
I have a Wicket component that takes IModel<List<Person>>, and allows you to view, remove, and add Persons to the list.
I would like to write a wrapper which implements IModel<List<Person>>, but which is backed by a PropertyModel<List<Long>> from the original domain object.
View-only is easy (Scala syntax for brevity):
class PersonModel(wrappedModel: IModel[List[Long]]) extends LoadableDetachableModel[List[Person]] {
#SpringBean dao: PersonDao =_
def load: List[Person] = {
// Returns a collection of Persons for each id
wrappedModel.getObject().map { id: Long =>
dao.getPerson(id)
}
}
}
But how might I write this to allow for adding and removing from the original List of Longs?
Or is a Model not the best place to do this translation?
Thanks!
You can do something like this:
class PersonModel extends Model<List<Person>> {
private transient List<Person> cache;
private IModel<List<String>> idModel;
public PersonModel( IModel<List<String>> idModel ) {
this.idModel = idModel;
}
public List<Person> getObject() {
if ( cache == null ) {
cache = convertIdsToPersons( idModel.getObject() );
return cache;
}
public void setObject( List<Person> ob ) {
cache = null;
idModel.setObject( convertPersonsToIds( ob ) );
}
}
This isn't very good code but it shows the general idea. One thing you need to consider is how this whole thing will be serialised between requests, you might be better off extending LoadableDetachableModel instead.
Another thing is the cache: it's there to avoid having to convert the list every time getObject() is called within a request. You may or may not need it in practice (depends on a lot of factors, including the speed of the conversion), but if you use it, it means that if something else is modifying the underlying collection, the changes may not be picked up by this model.
I'm not quite sure I understand your question and I don't understand the syntax of Scala.
But, to remove an entity from a list, you can provide a link that simply removes it using your dao. You must be using a repeater to populate your Person list so each repeater entry will have its own Model which can be passed to the deletion link.
Take a look at this Wicket example that uses a link with a repeater to select a contact. You just need to adapt it to delete your Person instead of selecting it.
As for modifying the original list of Longs, you can use the ListView.removeLink() method to get a link component that removes an entry from the backing list.
i have a question.i have a method (Filter),i want to pass T dynamic.but it dosen`t accept.how can i do it?
public List<T> Filter<T>(string TypeOfCompare)
{
List<T> ReturnList2 = new List<T>();
return ReturnList2;
}
IList MakeListOfType(Type listType)
{
Type listType1 = typeof(List<>);
Type specificListType = listType.MakeGenericType(listType1);
return (IList)Activator.CreateInstance(specificListType);
}
Filter < ConstructGenericList(h) > ("s");
IList MakeListOfType(Type listType)
{
Type listType1 = typeof(List<>);
Type specificListType = listType.MakeGenericType(listType1);
return (IList)Activator.CreateInstance(specificListType);
}
It should be the other way round, you should call MakeGenericType on the generic type definition, not on the generic type argument. So the code becomes this:
IList MakeListOfType(Type elementType)
{
Type listType = typeof(List<>);
Type specificListType = listType.MakeGenericType(elementType);
return (IList)Activator.CreateInstance(specificListType);
}
(note that I changed the variables names to make the code clearer)
Generic parameters must have a type able to be determined at compile time (without resorting to something like functional type inference that some other languages have). So, you can't just stick a function between the angle brackets to get the type you want.
Edit:
Now that I know what you're trying to do, I would suggest a different approach entirely.
You mention that you are using Entity Framework, and you are trying to use one method to get a list of different types of objects. Those objects -- like Student and Teacher -- must have something in common, though, else you would not be trying to use the same method to retrieve a list of them. For example, you may just be wanting to display a name and have an ID to use as a key.
In that case, I would suggest defining an interface that has the properties common to Student, Teacher, etc. that you actually need, then returning a list of that interface type. Within the method, you would essentially be using a variant of the factory pattern.
So, you could define an interface like:
public interface INamedPerson
{
int ID { get; }
string FirstName { get; }
string LastName { get; }
}
Make your entities implement this interface. Auto-generated entities are (typically) partial classes, so in your own, new code files (not in the auto-generated code files themselves), you would do something like:
public partial class Student : INamedPerson
{
public int ID
{
get
{
return StudentId;
}
}
}
and
public partial class Teacher : INamedPerson
{
public int ID
{
get
{
return TeacherId;
}
}
}
Now, you may not even need to add the ID property if you already have it. However, if the identity property in each class is different, this adapter can be one way to implement the interface you need.
Then, for the method itself, an example would be:
public List<INamedPerson> MakeListOfType(Type type)
{
if (type == typeof(Student))
{
// Get your list of students. I'll just use a made-up
// method that returns List<Student>.
return GetStudentList().Select<Student, INamedPerson>(s => (INamedPerson)s)
.ToList<INamedPerson>();
}
if (type == typeof(Teacher))
{
return GetTeacherList().Select<Teacher, INamedPerson>(t => (INamedPerson)t)
.ToList<INamedPerson>();
}
throw new ArgumentException("Invalid type.");
}
Now, there are certainly ways to refine this pattern. If you have a lot of related classes, you may want to use some sort of dependency injection framework. Also, you may notice that there is a lot of duplication of code. You could instead pass a function (like GetStudentList or GetTeacherList) by doing something like
public List<INamedPerson> GetListFromFunction<T>(Func<IEnumerable<T>> theFunction) where T : INamedPerson
{
return theFunction().Select<T, INamedPerson>(t => (INamedPerson)t).ToList<INamedPerson>();
}
Of course, using this function requires, once again, the type passed in to be known at compile time. However, at some point, you're going to have to decide on a type, so maybe that is the appropriate time. Further, you can make your life a little simpler by leaving off the generic type at method call time; as long as you are passing in a function that takes no arguments and returns an IEnumerable of objects of the same type that implement INamedPerson, the compiler can figure out what to use for the generic type T.