Rx: operator for getting first and most recent value from an Observable stream - system.reactive

For an Rx based change tracking solution I am in need of an operator which can get me the first and most recent item in an observable sequence.
How would I write an Rx operator that produces the following marble diagram (Note: the brackets are used just to lineup the items...I'm not sure how best to represent this in text):
xs:---[a ]---[b ]-----[c ]-----[d ]---------|
desired:---[a,a]---[a,b]-----[a,c]-----[a,d]---------|

Using the same naming as #Wilka you can use the below extension which is somewhat self-explanatory:
public static IObservable<TResult> FirstAndLatest<T, TResult>(this IObservable<T> source, Func<T,T,TResult> func)
{
var published = source.Publish().RefCount();
var first = published.Take(1);
return first.CombineLatest(published, func);
}
Note that it doesn't necessarily return a Tuple, but rather gives you the option of passing a selector function on the result. This keeps it in line with the underlying primary operation (CombineLatest). This is obviously easily changed.
Usage (if you want Tuples in the resulting stream):
Observable.Interval(TimeSpan.FromSeconds(0.1))
.FirstAndLatest((a,b) => Tuple.Create(a,b))
.Subscribe(Console.WriteLine);

Try this:
public static IObservable<Tuple<T, T>> FirstAndLatest<T>(
this IObservable<T> source)
{
return
source
.Take(1)
.Repeat()
.Zip(source, (x0, xn) => Tuple.Create(x0, xn));
}
Simple, huh?
Or, as an alternative to share the underlying source, try this:
public static IObservable<Tuple<T, T>> FirstAndLatest<T>(
this IObservable<T> source)
{
return
source.Publish(
s =>
s.Take(1)
.Repeat()
.Zip(s, (x0, xn) => Tuple.Create(x0, xn)));
}
WHOOPS! Scratch this. It doesn't work. It essentially keeps producing a pair of the latest values. Publishing like this isn't working. The original implementation is the best.

I suspect there's a much better way of doing this (and I dislike using Do), but you could create an operator like this
public static IObservable<Tuple<T, T>> FirstAndLatest2<T>(this IObservable<T> source)
{
return Observable.Defer(() => {
bool hasFirst = false;
T first = default(T);
return source
.Do(item =>
{
if (!hasFirst)
{
hasFirst = true;
first = item;
}
})
.Select(current => Tuple.Create(first, current));
});
}
Then you would use it like this:
Observable.Interval(TimeSpan.FromSeconds(0.1))
.FirstAndLatest()
.Subscribe(Console.WriteLine);

Related

Mocking DbFunctions.Like

I've tried to mock DbFunctions.Like function by following most popular answer from this ticket and creating it's local implementation like this:
public static class DbFunctions
{
[DbFunction("Edm", "TruncateTime")]
public static DateTime? TruncateTime(DateTime? dateValue)
=> dateValue?.Date;
[DbFunction("Edm", "Like")]
public static bool Like(string searchString, string likeExpression)
=> Regex.IsMatch(searchString, $"^{likeExpression.Replace("%", ".*")}$");
[DbFunction("Edm", "Right")]
public static string Right(string stringArgument, long? length)
=> stringArgument.Substring(stringArgument.Length - ((int?) length ?? 0));
}
And using this function instead of System.Entity.DbFunctions in queries:
var query = Context.Items.AsQueryable();
if (!string.IsNullOrWhiteSpace(Number))
{
var valuesToSearch = Number.Split(';')
.Select(number => number.Trim())
.AsEnumerable();
query = query.Where(x => valuesToSearch.Any(v => DbFunctions.Like(x.Number, v)));
}
It works fine for e.g. "TruncateTime" or "Right" functions.
When I'm debugging the solution the sql versions of the functions are invoked and when I'm running unit tests the local one is invoked and tests are passing.
When it comes to "Like" I'm still getting NotSupportedException:
Is it impossible to mock DbFunctions.Like in the same manner like other system functions?
I'm using EF6 v6.4.4, Moq v4.14.1 and nUnit v3.12.0.
DbFunctions.Like does not have the DbFunctionAttribute, and therefore can't be mocked that way. You can, as a workaround, use SqlFunctions.PatIndex. PatIndex will return the position of the first occurrence of the given pattern in a string or 0 if it does not occur at all.
[DbFunction("SqlServer", "PATINDEX")]
public static int? Like(string searchString, string likeExpression)
=> Regex.IsMatch(searchString, $"^{likeExpression.Replace("%", ".*")}$") ? 1 : 0;
and
query = query.Where(x => valuesToSearch.Any(v => DbFunctions.Like(x.Number, v) > 0));
could work for you. It's not great in terms of readability though.

Merging Entity Framework Expression Trees

I'm looking for a way to merge multiple expression trees in order to build selectors for an Entity Framework query. The query knows which columns to select based on user-provided parameters. For example, a basic query returns ID/Name columns of an entity. If a parameter is explicitly set to also retrieve the Description column, then the query will return ID/Name/Description.
So, what I need it the code for the MergeExpressions method in the following code.
Expression<Func<T, TDto>> selector1 = x => new TDto
{
Id = x.Id,
Name = x.Name
}
Expression<Func<T, TDto>> selector2 = x => new TDto
{
Description = x.Description
}
var selector = selector1;
if (includeDescription)
selector = MergeExpressions(selector1, selector2);
var results = repo.All().Select(selector).ToList();
Thank you.
Not sure for general case, but merging MemberInitExpression bodied lambdas like in your sample is relatively easy. All you need is to create another MemberInitExpression with combined Bindings:
static Expression<Func<TInput, TOutput>> MergeExpressions<TInput, TOutput>(Expression<Func<TInput, TOutput>> first, Expression<Func<TInput, TOutput>> second)
{
Debug.Assert(first != null && first.Body.NodeType == ExpressionType.MemberInit);
Debug.Assert(second != null && second.Body.NodeType == ExpressionType.MemberInit);
var firstBody = (MemberInitExpression)first.Body;
var secondBody = (MemberInitExpression)second.Body.ReplaceParameter(second.Parameters[0], first.Parameters[0]);
var body = firstBody.Update(firstBody.NewExpression, firstBody.Bindings.Union(secondBody.Bindings));
return first.Update(body, first.Parameters);
}
Note that the lambda expressions must be bound to one and the same parameters, so the above code uses the following parameter replacer helper to rebind second lambda body to the first lambda parameter:
public static partial class ExpressionUtils
{
public static Expression ReplaceParameter(this Expression expression, ParameterExpression source, Expression target)
{
return new ParameterReplacer { Source = source, Target = target }.Visit(expression);
}
class ParameterReplacer : ExpressionVisitor
{
public ParameterExpression Source;
public Expression Target;
protected override Expression VisitParameter(ParameterExpression node)
{
return node == Source ? Target : base.VisitParameter(node);
}
}
}
Check out PredicateBuilder.
Example:
Expression<Func<Customer, bool>> expr1 = (Customer c) => c.CompanyName.StartsWith("A");
Expression<Func<Customer, bool>> expr2 = (Customer c) => c.CompanyName.Contains("B");
var expr3 = PredicateBuilder.And(expr1, expr2);
var query = context.Customers.Where(expr3);
or
var expr3 = expr1.And(expr2);
var query = context.Customers.Where(expr3);
I do this kind of thing with extension methods. Its syntactically a bit nicer than using expression trees everywhere. I call this composable repositories.
I also wrote a tool (LinqExpander) to combine the expression trees of different extension methods togeather, which is especially useful for doing projection (selects) from your database. This is only nessacary when you are doing things with sub-entities. (see my post here: Composable Repositories - Nesting extensions)
usage would be something along the lines of:
var dtos = context.Table
.ThingsIWant() //filter the set
.ToDtos() //project from database model to something else (your Selector)
.ToArray();//enumerate the set
ToDtos might look something like:
public static IQueryable<DtoType> ToDtos(this IQueryable<DatabaseType> things)
{
return things.Select(x=> new DtoType{ Thing = x.Thing ... });
}
You want to merge two selects togeather (im assuming to avoid an underfetch but this seems a bit wierd). I would do this by using a projection like this:
context.Table
.AsExpandable()
.Select(x=>new {
Dto1 = x.ToDto1(),
Dto2 = x.ToDto2()
})
.ToArray();
if you really wanted it to return a single entity like this you could probably do something like:
context.Table
.AsExpandable()
.Select(x=> ToDto1(x).ToDto2(x));
but I havent ever tried this.
As this uses a sub projection you will need the .AsExpandable extensions.

How do I merge several observables using WhenAny(...) in ReactiveUI?

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.

How to resolve generic type at runtime

I'm trying to build a command processor that can take any command that implements a marker interface (or maybe descends from a base class). The processor will handle the command that it is asked to process. However I'm struggling with resolving the true generic type as Resolve(Type) returns an object.
I'm not sure is how to cast this if at all possible?
public void Process(ICommand command)
{
var c = command.GetType();
var t = typeof(ICommandHandler<>).MakeGenericType(new[] { c });
var o = container.Resolve(t);
//((ICommandHandler)o).Handle(command); *** This doesn't work
}
The calling code would be something like this -
Dispatcher.Process(new SomeCommand(Guid.NewGuid(),"Param1",12345));
If you absolutely have to call the ICommandHandler<T>.Handle method and you have no other control over the design of the system, then reflection may be your only choice. There's no great way to deal with the switch from generic to non-generic.
Otherwise, you may have a couple of options.
First, if your Dispatcher.Process can be made generic, you can save all the casting.
public static class Dispatcher
{
public static void Process<T>(T command) where T : ICommand
{
var handler = container.Resolve<ICommandHandler<T>>();
handler.Handle(command);
}
}
This is a pretty common solution to a problem like this that I've seen out in the wild.
If you can't do that, then you may be able to make your ICommandHandler<T> interface implement a non-generic ICommandHandler base interface.
public interface ICommandHandler
{
void Handle(ICommand command);
}
public interface ICommandHandler<T> : ICommandHandler
{
void Handle(T command);
}
In this latter case you'd have to switch your strongly-typed command handler implementations to call the same internal logic for generic or basic handling or you'll get different handling based on the call, which would be bad:
public class SomeCommandHandler : ICommandHandler<SomeCommand>
{
public void Handle(ICommand command)
{
var castCommand = command as SomeCommand;
if(castCommand == null)
{
throw new NotSupportedException("Wrong command type.");
}
// Hand off to the strongly-typed version.
this.Handle(castCommand);
}
public void Handle(SomeCommand command)
{
// Here's the actual handling logic.
}
}
Then when you resolve the strongly-typed ICommandHandler<T> your cast down to ICommandHandler (as shown in your question's sample code) will work.
This is also a pretty common solution, but I've seen it more in systems that existed before generics were available where an updated API was being added.
However, in all cases here, the problem really isn't that Autofac is returning an object; it's a class/type design problem that affects any generic-to-non-generic conversion scenario.
Using Reflection - but is this the best way to approach this?
public void Process(Command command)
{
var c = command.GetType();
var ot = typeof(ICommandHandler<>);
var type = ot.MakeGenericType(new[] { c });
var mi = type.GetMethod("Handle");
var o = container.Resolve(type);
mi.Invoke(o, new object[] { command });
}

Autofac: Injected collection is not empty (contains one item)

I'm using Autofac 2.4.4.705.
The output of the following code is: 1 (which means the resolved collection contains one item. I thought it should be empty)
class Program
{
static void Main(string[] args)
{
var builder = new Autofac.ContainerBuilder();
builder.RegisterModule(new AutofacModule());
using (var container = builder.Build())
{
var x = container.Resolve<ObservableCollection<A>>();
Console.WriteLine(x.Count);
}
}
}
class A
{
}
class AutofacModule : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly());
builder.RegisterGeneric(typeof(ObservableCollection<>))
.As(typeof(ObservableCollection<>));
}
}
It seems the issue is cause by:
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly());
If I remove it from AutofacModule, then the output is 0.
Any ideas?
Thanks
Update:
Ah, I think I understand now. Autofac thought I want to resolve all types of A, and there is one type of A in this example (A itself), so the ObservableCollection contains one item. I previously thought only IEnumerable<> has this behavior. But it seems subtypes of IEnumerable<> also have this behavior.
But sometimes what I really want is to inject an collection, for example, sometime I need to inject DispacherNotifiedObservableCollection into my ViewModels. Any workarounds?
Update 2:
Based on the answer of Nicholas Blumhardt, I changed my code to:
builder.RegisterGeneric(typeof(ExtendedObservableCollection<>))
.As(typeof(IObservableCollection<>))
.UsingConstructor();
public interface IObservableCollection<T> :
IList<T>, ICollection<T>, IEnumerable<T>, INotifyCollectionChanged, INotifyPropertyChanged
{
void AddRange(IEnumerable<T> list);
void Sort<TKey>(Func<T, TKey> keySelector, System.ComponentModel.ListSortDirection direction);
void Sort<TKey>(Func<T, TKey> keySelector, IComparer<TKey> comparer);
}
Now everything works fine. Thanks!
The behavior you're seeing is a result of the ObservableCollection type having a constructor that accepts IEnumerable.
You can change this to use the default constructor using the UsingConstructor() option.
ObservableCollection itself might not be a very good contract to depend on though- it is a bit unclear what the semantics should generally be. Wrapping it in a specialized component with it's own interface is the better option.