-
-
Notifications
You must be signed in to change notification settings - Fork 798
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
New LookupOrFallbackDefaultValueProvider
base class for custom default value providers
#536
New LookupOrFallbackDefaultValueProvider
base class for custom default value providers
#536
Conversation
This abstract base class offers the basic functionality required by providers akin to the empty default value provider. That is, it allows setting up different value generation strategies for different types, and it can fall back to a default generation strategy if a request is made for which no specific strategy is available. It also handles task types such that values are automatically wrapped as completed `Task<TResult>` or `ValueTask<TResult>`. Both `EmptyDefaultValueProvider` and `MockDefaultValueProvider` are refactored to derive from this type (which incidentally makes them a tiny bit faster).
But why is it sealed? I would like to override it to customize batch of types instead of Register(...) call for each type. Something like this: protected override object GetDefaultValue(Type type, Mock mock)
{
var enumerableType = typeof(IEnumerable<>).MakeGenericType(type.GetGenericArguments());
if (enumerableType.IsAssignableFrom(type))
{
var listType = typeof(List<>).MakeGenericType(type.GetGenericArguments());
return Activator.CreateInstance(listType);
}
base.GetDefaultValue(type, mock);
} |
In order to guarantee a certain behavior with generic and array types. (And because I believe that composition is generally better for composing behavior than inheritance, so I tend to define methods as either abstract, or sealed... but not virtual.) If that's not what you want, you can always subclass the base class |
Yes, DefaultValueProvider is good way but how to get empty values for other types that are not covered my |
Sorry I forgot to say, instead of trying to override Also, you can always use composition with / delegation to another default value provider (e.g. |
I cannot use |
(You cannot override, but you can use composition.)
Glad to hear. You're welcome! |
Do you mean |
Sorry, you're right of course... I seem to have mis-remembered those methods' accessibility. Composition indeed doesn't seem possible in this case (which is probably a design flaw). |
If so, how can I make a customized value provider which falls back to the Mock object if I did not register the type? |
This adds a new base class
LookupOrFallbackDefaultValueProvider
, which builds on top ofDefaultValueProvider
, to Moq's public API.This type becomes the new base class for both
EmptyDefaultValueProvider
andMockDefaultValueProvider
.It has built-in support for task types
Task
,Task<TResult>
, andValueTask<TResult>
.It also provides enough customizability for folks to easily create their own default value providers that work like the empty default value provider. Here's an example of a provider that will produce empty collections for
IReadOnlyList<T>
:For the rationale behind this new type, and the reasoning why it doesn't come preconfigured as an empty default value provider supporting all standard collection types from the .NET BCL, see #173.
Perhaps we can add a customizable or expanded empty default value provider at a later time if there's still widespread demand / need for it.