Skip to content
This repository has been archived by the owner on Dec 14, 2018. It is now read-only.

Add extension methods to IEnumerable<OptionsDescriptor<T>> #1787

Closed
yishaigalatzer opened this issue Jan 9, 2015 · 5 comments
Closed

Add extension methods to IEnumerable<OptionsDescriptor<T>> #1787

yishaigalatzer opened this issue Jan 9, 2015 · 5 comments

Comments

@yishaigalatzer
Copy link
Contributor

It is currently rather cumbersome to configure options in any of the lists in MvcOptions. The user has to write selector code to get to the descriptor objects, and then get the actual instance. For example

services.ConfigureOptions<MvcOptions>(options => 
    options.InputFormatters.Single(fd => fd.Instance is JsonInputFormatter).Instance.XXXX

Instead we should have a set of extension methods allowing easy access to the descriptors/instances

Here is an initial suggestion - @rynowak lets discuss and update

public static TInstance InstanceOf<TInstance>(this IEnumerable<OptionsDescriptor<TInstance>> collection);
public static TInstance InstanceOfOrDefault<TInstance>(this IEnumerable<OptionsDescriptor<TInstance>> collection);
public static IEnumerable<TInstance> InstancesOf<TInstance>(this IEnumerable<OptionsDescriptor<TInstance>> collection);
public static void RemoveTypesOf<TDescriptor>(this IList<OptionsDescriptor<TDescriptor>> collection);

perhaps we should also consider a replace in place extension, so a customized options can come in the exact same spot the one it replaced is in.
#1744

@tonysneed
Copy link
Contributor

I'm ready to do this one now, and I can submit a PR for it.

@tonysneed
Copy link
Contributor

It looks like extensions to IEnumerable<OptionDescriptor> aren't going to provide the desired result. For example this method:

public static TInstance InstanceOf<TInstance>([NotNull] this 
    IEnumerable<OptionDescriptor<TInstance>> descriptors)

Called by this code:

var formatter = new MvcOptions().InputFormatters.InstanceOf<JsonInputFormatter>();

Will produce a CS1929 compilation error: The extension method requires a receiver of type IEnumerable<OptionDescriptor<JsonInputFormatter>>.

I would like to suggest the following (for both input and output descriptors):

public static TInstance InstanceOf<TInstance>([NotNull] this
    IEnumerable<InputFormatterDescriptor> descriptors)

@yishaigalatzer
Copy link
Contributor Author

You can alternatively define the IOptionsDescriptor<T> interface and use InstanceOf<T>(IEnumerable<object>)

e.g.

public class InputFormatterDescriptor : OptionDescriptor<IInputFormatter>, 
                   IOptionDescriptor<IInputFormatter>
{
     ...
}

and

public interface IOptionDescriptor<out TOption>
{
    Type OptionType { get; }
    TOption Instance { get; }
}

and

public class OptionDescriptor<TOption> : IOptionDescriptor<TOption>
{
    ....
}

and finally

public static TInstance InstanceOf<TInstance>([NotNull] this IEnumerable<IOptionDescriptor<object>> descriptors) 
{
    return default(TInstance);
}

@tonysneed
Copy link
Contributor

Perfect ... this will work for InstanceOf, InstanceOfOrDefault and InstancesOf. However, RemoveTypesOf becomes a bit problematic, because IList is not covariant. For example, this method:

public static void RemoveTypesOf<TInstance>([NotNull] this 
    IList<IOptionDescriptor<object>> descriptors)

Will result in a compilation error when called by this method:

new MvcOptions().InputFormatters.RemoveTypesOf<JsonInputFormatter>();

Because it can't convert from InputFormatterDescriptor to IOptionDescriptor<object>.

Instead, RemoveTypesOf will need to be defined like so:

public static void RemoveTypesOf<TInstance, TOptionDescriptor>([NotNull] this
    IList<TOptionDescriptor> descriptors)
    where TOptionDescriptor : IOptionDescriptor<object>

And it will need to be called with an extra type argument, like so:

new MvcOptions().InputFormatters.RemoveTypesOf<JsonInputFormatter, 
    InputFormatterDescriptor>();

Which is not very intuitive. Would you like me to add a RemoveTypesOf method anyway?

@dougbu
Copy link
Member

dougbu commented Feb 9, 2015

Fixed with commits 2c21c7c and 45aae59.

@dougbu dougbu closed this as completed Feb 9, 2015
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants