Is there a way to find the declared generic argument type of an instance of an Action delegate?
In the following code the WriteGenericArgumentType
function expects and instance of Action<String>
but because Action<in T>
allows for contravariance callers of the function are able to call it with Action<Object>
.
static void Main( )
{
WriteGenericArgumentType( new Action<string>( s => { } ) );
WriteGenericArgumentType( new Action<object>( o => { } ) );
}
static void WriteGenericArgumentType( Action<string> action )
{
Console.WriteLine( DiscoverGenericArgumentType( action ).Name );
}
static Type DiscoverGenericArgumentType( Delegate action )
{
return action.GetType().GetGenericArguments()[0];
}
However, I need to be able to discover the generic argument type that was defined in the signature of WriteGenericArgumentType
from the instance of the delegate that is passed to DiscoverGenericArgumentType
.
When the code runs I get the following output:
String
Object
But I need it to be:
String
String
For my purposes I cannot change the signature of DiscoverGenericArgumentType
and I need that function to return string
as the type.
I know I can create my own generic delegate type that doesn't allow contravariance but I'm looking for a way to not have to change the signature of the API if possible.
Any ideas?
You won't be able to from inspecting the instance of the Action<in T>
passed in. As you see, it actually is an Action<object>
and there's nothing linking back to the fact that you wanted an Action<string>
.
However, instead of looking at the parameter, you should look at the signature of the method . This will always be Action<string>
and reflecting/inspecting that will always give you the output you are looking for.
You can't do this, because you're not changing the object. Consider:
static void WriteGenericArgumentType(Action<string> action)
{
Action<object> action2 = action;
Console.WriteLine(DiscoverGenericArgumentType(action).Name);
Console.WriteLine(DiscoverGenericArgumentType(action2).Name);
}
You're passing an identical reference to DiscoverGenericArgumentType
in both cases, so how could it possibly tell what you mean?
Would this work for you?
static Type DiscoverGenericArgumentType<T>(Action<T> action )
{
return typeof(T);
}
It does what you're asking for, but I don't know if you are able to change your method signature to require a specific delegate signature.
One way I can possibly get around this is to wrap the delegate / discover the type at the point I for sure know the type like so:
static void Main()
{
WriteGenericArgumentType( new Action<string>( s => { } ) );
WriteGenericArgumentType( new Action<object>( o => { } ) );
}
static void WriteGenericArgumentType( Action<string> action )
{
Console.WriteLine( DiscoverGenericArgumentType( Wrap( action ) ).Name );
}
static Type DiscoverGenericArgumentType( Delegate action )
{
return action.GetType().GetGenericArguments()[ 0 ];
}
static Action<T> Wrap<T>( Action<T> action )
{
return new Action<T>( o => action( o ) );
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.