We have a generic extension method which works only for objects that supports both the INotifyCollectionChanged and IEnumerable interfaces. It's written like this:
public static class SomeExtensions
{
public static void DoSomething<T>(this T item)
where T : INotifyCollectionChanged, IEnumerable
{
// Do something
}
}
The following compiles fine since ObservableCollection<string>
implements both interfaces and thanks to the 'var' keyword, knownType is strongly typed:
var knownType = new ObservableCollection<string>();
knownType.DoSomething();
However, we are trying to call this from a ValueConverter. The problem is the incoming value is of type object
and even though we can test that the passed-in object does implement both interfaces, we can't figure out how to explicitly cast it so we can call that generic extension method. This doesn't work (obviously)...
object unknownType = new ObservableCollection<string>();
((INotifyCollectionChanged,IEnumerable)unknownType).DoSomething();
So how can you cast an object to multiple interfaces so you can call the generic? Not even sure it's possible.
It will give a compile-time error if you try to instantiate a generic type using a type that is not allowed by the specified constraints. You can specify one or more constraints on the generic type using the where clause after the generic type name.
Value type constraint If we declare the generic class using the following code then we will get a compile-time error if we try to substitute a reference type for the type parameter.
Object, you'll apply constraints to the type parameter. For example, the base class constraint tells the compiler that only objects of this type or derived from this type will be used as type arguments.
NET class library defines several generic interfaces for use with the collection classes in the System. Collections. Generic namespace.
The cleanest way I can think to do this would be dynamic
. However, because extension methods don't play nice with dynamic
(see blelow), you'll have to reference the extension method explicitly.
Extensions.DoSomething(unknownType as dynamic);
EDIT As a warning aginst the gotcha I ran into here, note that calling the method with explicit dyanmic
as the type argument (via DoSomething<dynamic>
) will not work - it causes compile errors when trying to match against multiple constraints. In addition, when not using multiple constraints, this results in the dynamic
resolving based on the passed variable's compile-time type, not the runtime type.
This will result in a call to Extensions.UnknownType<dynamic>
, the dynamic
of which will resolve at runtime - meaning it'll use the fully derived type of the given parameter. As long as this parameter implements the desired interfaces, off you go.
Be wary as, like much dynamic
code, this could encounter issues that won't be seen until runtime. Use sparingly!
If you make multiple calls with the same generic paremeters, you might be better off adding a generic helper method in your converter and then calling that using value as dynamic
Addendum:
When using dynamic
, anything called against the dynamic
object will attempt to resolve as a member of the given type at runtime, but will not look up Extension Methods, since they inherently exist in a completely different class, often a different assembly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With