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

Convenience methods for creating Owned<T> instances #156

Open
jnm2 opened this issue Oct 16, 2021 · 3 comments
Open

Convenience methods for creating Owned<T> instances #156

jnm2 opened this issue Oct 16, 2021 · 3 comments

Comments

@jnm2
Copy link
Contributor

jnm2 commented Oct 16, 2021

Once a lot of a codebase has necessarily taken a dependency on Owned<T> so that StrongInject can wire everything up, many places remain that need to create their own Owned instances. This is handy for many tests and smaller executables in a project that don't really need StrongInject and can do their own wiring with a few calls.

Instead of: new Owned<SomePotentiallyLongTypeName>(value, () => { })
Friendly: Owned.WithoutDisposal(value)

Instead of: new Owned<SomePotentiallyLongTypeName>(value, value.Dispose)
Friendly: Owned.WithDisposal(value)

Instead of: new Owned<T>(value, () => (value as IDisposable)?.Dispose())
Friendly: Owned.WithDisposal(value)

Instead of: new Owned<SomeType>(value, () => { value.Dispose(); dependency1.Dispose(); dependency2.Dispose(); })
Friendly: Owned.WithDisposal(value, dependency1, dependency2) or
Friendly: Owned.WithDisposal(value, alsoDispose: new[] { dependency1, dependency2 })

Here's a rough draft for what I've already found useful, and I'm happy to do the implementation:

namespace StrongInject;

public static class Owned
{
    /// <summary>
    /// Nothing happens when the <see cref="Owned{T}"/> is disposed, even if <paramref name="value"/>
    /// is disposable.
    /// </summary>
    public static Owned<T> WithoutDisposal<T>(T value)
    {
        return new(value, dispose: null);
    }

    /// <summary>
    /// <para>
    /// When the <see cref="Owned{T}"/> is disposed, <paramref name="value"/> is disposed. If
    /// <paramref name="value"/> does not implement <see cref="IDisposable"/>, the behavior is
    /// the same as <see cref="WithoutDisposal{T}(T)"/>.
    /// </para>
    /// </summary>
    public static Owned<T> WithDisposal<T>(T value)
    {
        // T is not constrained to IDisposable. If it was, call sites using generic types would be penalized.
        return new(value, dispose: value is IDisposable disposable
            ? disposable.Dispose
            : null);
    }

    /// <summary>
    /// <para>
    /// When the <see cref="Owned{T}"/> is disposed, <paramref name="value"/> is disposed first and then
    /// the items in <paramref name="alsoDispose"/> are disposed in the order they appear.
    /// </para>
    /// <para>
    /// If <paramref name="value"/> does not implement <see cref="IDisposable"/>, the items in
    /// <paramref name="alsoDispose"/> will still be disposed.
    /// </para>
    /// </summary>
    public static Owned<T> WithDisposal<T>(T value, params IDisposable[] alsoDispose)
    {
        return new(value, dispose: () =>
        {
            (value as IDisposable)?.Dispose();

            foreach (var disposable in alsoDispose)
                disposable.Dispose();
        });
    }
}

An AsyncOwned static class would be similar.

@YairHalberstadt
Copy link
Owner

I'm not sure about this. At the moment StrongInject only contains types that help with DI itself. Do we want to start adding in types which aren't actually helpful for DI, but for testing code which uses it, especially when it's super simple to write this yourself?

@jnm2
Copy link
Contributor Author

jnm2 commented Oct 22, 2021

I would look at this as having to do with the definition of Owned<T> as a library type and as being completely separate from the source generator. What would it look like if the BCL maintained this type, or someone else?

On the other hand it's not a huge deal if I copy and paste this file as needed.

@jnm2
Copy link
Contributor Author

jnm2 commented Oct 23, 2021

Updated the definitions. Not sure where I thought I was going with disposeFirst. 😆

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants