Skip to content

Commit

Permalink
#11 Custom expression visitors can be added to the QbservableServiceO…
Browse files Browse the repository at this point in the history
…ptions instance that you pass to the service operators/factories.
  • Loading branch information
RxDave committed Jun 22, 2016
1 parent dce014f commit 41b08af
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ internal sealed class StreamQbservableProtocol : QbservableProtocol<Stream, Stre
private readonly IRemotingFormatter formatter;

public StreamQbservableProtocol(object clientId, Stream stream, IRemotingFormatter formatter, CancellationToken cancel)
: base(clientId, stream, cancel)
: base(clientId, stream, cancel)
{
Contract.Requires(clientId != null);
Contract.Requires(stream != null);
Expand All @@ -32,7 +32,7 @@ public StreamQbservableProtocol(object clientId, Stream stream, IRemotingFormatt
}

public StreamQbservableProtocol(Stream stream, IRemotingFormatter formatter, QbservableServiceOptions serviceOptions, CancellationToken cancel)
: base(stream, serviceOptions, cancel)
: base(stream, serviceOptions, cancel)
{
Contract.Requires(stream != null);
Contract.Requires(formatter != null);
Expand Down
70 changes: 45 additions & 25 deletions Source/Qactive/QbservableServiceOptions.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics.Contracts;
using System.Linq.Expressions;

namespace Qactive
{
Expand All @@ -11,26 +14,35 @@ public sealed class QbservableServiceOptions
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "It's immutable due to the frozen flag.")]
public static readonly QbservableServiceOptions Default = new QbservableServiceOptions()
{
frozen = true,
IsFrozen = true,
evaluationContext = new ServiceEvaluationContext()
};

[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "It's immutable due to the frozen flag.")]
public static readonly QbservableServiceOptions Unrestricted = new QbservableServiceOptions()
{
frozen = true,
IsFrozen = true,
allowExpressionsUnrestricted = true,
enableDuplex = true,
evaluationContext = new ServiceEvaluationContext()
};

private bool frozen;
private readonly List<ExpressionVisitor> visitors = new List<ExpressionVisitor>();
private bool sendServerErrorsToClients;
private bool enableDuplex;
private bool allowExpressionsUnrestricted;
private ExpressionOptions expressionOptions;
private ServiceEvaluationContext evaluationContext;

[ContractInvariantMethod]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic", Justification = "Required for code contracts.")]
private void ObjectInvariant()
{
Contract.Invariant(visitors != null);
}

public bool IsFrozen { get; private set; }

public bool SendServerErrorsToClients
{
get
Expand All @@ -39,10 +51,7 @@ public bool SendServerErrorsToClients
}
set
{
if (frozen)
{
throw new NotSupportedException();
}
Contract.Requires(!IsFrozen);

sendServerErrorsToClients = value;
}
Expand All @@ -56,10 +65,7 @@ public bool EnableDuplex
}
set
{
if (frozen)
{
throw new NotSupportedException();
}
Contract.Requires(!IsFrozen);

enableDuplex = value;
}
Expand All @@ -73,15 +79,18 @@ public bool AllowExpressionsUnrestricted
}
set
{
if (frozen)
{
throw new NotSupportedException();
}
Contract.Requires(!IsFrozen);

allowExpressionsUnrestricted = value;
}
}

#if READONLYCOLLECTIONS
public IReadOnlyList<ExpressionVisitor> Visitors => visitors.AsReadOnly();
#else
public ReadOnlyCollection<ExpressionVisitor> Visitors => visitors.AsReadOnly();
#endif

public ExpressionOptions ExpressionOptions
{
get
Expand All @@ -90,10 +99,7 @@ public ExpressionOptions ExpressionOptions
}
set
{
if (frozen)
{
throw new NotSupportedException();
}
Contract.Requires(!IsFrozen);

expressionOptions = value;
}
Expand All @@ -114,22 +120,21 @@ public ServiceEvaluationContext EvaluationContext
}
set
{
if (frozen)
{
throw new NotSupportedException();
}
Contract.Requires(!IsFrozen);

evaluationContext = value;
}
}

public QbservableServiceOptions()
{
Contract.Ensures(!IsFrozen);
}

public QbservableServiceOptions(QbservableServiceOptions clone)
{
Contract.Requires(clone != null);
Contract.Ensures(!IsFrozen);

sendServerErrorsToClients = clone.sendServerErrorsToClients;
enableDuplex = clone.enableDuplex;
Expand All @@ -138,17 +143,32 @@ public QbservableServiceOptions(QbservableServiceOptions clone)
evaluationContext = clone.evaluationContext;
}

public QbservableServiceOptions Add(ExpressionVisitor visitor)
{
Contract.Requires(visitor != null);
Contract.Requires(!IsFrozen);
Contract.Ensures(Contract.Result<QbservableServiceOptions>() == this);
Contract.Ensures(Visitors.Count == Contract.OldValue(Visitors.Count) + 1);
Contract.Ensures(Contract.Exists(Visitors, v => v == visitor));

visitors.Add(visitor);

return this;
}

public QbservableServiceOptions Freeze()
{
Contract.Ensures(Contract.Result<QbservableServiceOptions>() != null);
Contract.Ensures(Contract.Result<QbservableServiceOptions>() == this);
Contract.Ensures(IsFrozen);

frozen = true;
IsFrozen = true;
return this;
}

public QbservableServiceOptions Clone()
{
Contract.Ensures(Contract.Result<QbservableServiceOptions>() != null);
Contract.Ensures(!Contract.Result<QbservableServiceOptions>().IsFrozen);

return new QbservableServiceOptions(this);
}
Expand Down
5 changes: 5 additions & 0 deletions Source/Qactive/ServerQuery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,11 @@ private Expression PrepareExpression(out IQbservableProvider realProvider)

preparedExpression = visitor.Visit(preparedExpression);

foreach (var customVisitor in Provider.Options.Visitors)
{
preparedExpression = customVisitor.Visit(preparedExpression);
}

Log.ServerRewrittenExpression(clientId, preparedExpression);

return preparedExpression;
Expand Down

0 comments on commit 41b08af

Please sign in to comment.