Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cache redirect proxies against root instances #67

Merged
merged 1 commit into from
Apr 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions src/DivertR/DiverterSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ public class DiverterSettings

public bool DefaultWithDummyRoot { get; }

public bool CacheRedirectProxies { get; }

public IDummyFactory DummyFactory { get; }

public ICallInvoker CallInvoker { get; }
Expand All @@ -41,18 +43,19 @@ public static DiverterSettings Global
}
}

public DiverterSettings(
IProxyFactory? proxyFactory = null,
public DiverterSettings(IProxyFactory? proxyFactory = null,
IDiverterProxyFactory? diverterProxyFactory = null,
IRedirectProxyDecorator? redirectProxyDecorator = null,
bool defaultWithDummyRoot = true,
bool cacheRedirectProxies = true,
IDummyFactory? dummyFactory = null,
ICallInvoker? callInvoker = null)
{
ProxyFactory = proxyFactory ?? new DispatchProxyFactory();
DiverterProxyFactory = diverterProxyFactory ?? new DiverterProxyFactory();
RedirectProxyDecorator = redirectProxyDecorator ?? new RedirectProxyDecorator();
DefaultWithDummyRoot = defaultWithDummyRoot;
CacheRedirectProxies = cacheRedirectProxies;
DummyFactory = dummyFactory ?? new DummyFactory();
CallInvoker = callInvoker ?? DefaultCallInvoker;
}
Expand Down
21 changes: 19 additions & 2 deletions src/DivertR/Redirect.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public class Redirect<TTarget> : IRedirect<TTarget> where TTarget : class?
private readonly IProxyFactory _proxyFactory;
private readonly Relay<TTarget> _relay;
private readonly RedirectProxyCall<TTarget> _redirectProxyCall;
private readonly ConditionalWeakTable<TTarget, TTarget> _proxyCache = new();

public Redirect(string? name = null, DiverterSettings? diverterSettings = null, IRedirectRepository? redirectRepository = null)
: this(RedirectId.From<TTarget>(name), new RedirectSet(diverterSettings), redirectRepository)
Expand Down Expand Up @@ -102,9 +103,25 @@ public TTarget Proxy(object? root)
[return: NotNull]
public TTarget Proxy(TTarget? root)
{
var proxy = _proxyFactory.CreateProxy(_redirectProxyCall, root);
TTarget proxy;

return RedirectSet.Settings.RedirectProxyDecorator.Decorate(this, proxy);
if (root is null || !RedirectSet.Settings.CacheRedirectProxies)
{
proxy = _proxyFactory.CreateProxy(_redirectProxyCall, root);
RedirectSet.Settings.RedirectProxyDecorator.Decorate(this, proxy);
}
else
{
proxy = _proxyCache.GetValue(root, x =>
{
var createdProxy = _proxyFactory.CreateProxy(_redirectProxyCall, x);
RedirectSet.Settings.RedirectProxyDecorator.Decorate(this, createdProxy);

return createdProxy;
});
}

return proxy!;
}

/// <inheritdoc />
Expand Down
29 changes: 29 additions & 0 deletions test/DivertR.UnitTests/RedirectTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,35 @@ public void GivenInvalidRootObjectType_WhenCreateProxyObject_ShouldThrowArgument
// ASSERT
testAction.ShouldThrow<ArgumentException>();
}

[Fact]
public void GivenDefaultDiverterSettings_WhenCreateProxiesWithSameRootInstance_ShouldCache()
{
// ARRANGE
var foo = new Foo();
var proxy = _redirect.Proxy(foo);

// ACT
var testProxy = _redirect.Proxy(foo);

// ASSERT
testProxy.ShouldBeSameAs(proxy);
}

[Fact]
public void GivenCacheRedirectProxiesDisabled_WhenCreateProxiesWithSameRootInstance_ShouldNotCache()
{
// ARRANGE
var redirect = new Redirect<IFoo>(new DiverterSettings(cacheRedirectProxies: false));
var foo = new Foo();
var proxy = redirect.Proxy(foo);

// ACT
var testProxy = redirect.Proxy(foo);

// ASSERT
testProxy.ShouldNotBeSameAs(proxy);
}

[Fact]
public void GivenStrictModeWithNoVia_ShouldThrowException()
Expand Down