Reputation: 1951
I'm trying to write a extension method of IThingRequest<TEntity>
, it returns Thing<TEntity>
. I would like the method to only return the underlying type of TEntity
not any other generic classes or interfaces it would implement. So, in the example below, the wish is that the return type should be Thing<Entity>
not Thing<GenericClass<Entity>>
.
The extensions method:
public static Thing<TEntity> DoStuff<TEntity>(IThingRequest<TEntity> request)
=> new Thing<TEntity>();
Calling the extension method:
public class Request : IThingRequest<GenericClass<Entity>>
{ }
var request = new Request();
var result = request.DoStuff();
The type of result is now Thing<GenericClass<Entity>>
.
My first instinct was that there would be a way to achieve this with where
, but I can't figure it out. I've also considered using reflections to get the non generic type of TEntity
and returning Thing<object>
but I believe that that would require casting where the DoStuff
method is used.
Any help is greatly appreciated!
Upvotes: 2
Views: 110
Reputation: 1951
Thanks for all the input!
I wanted a solution where I didn't have to cast the result from DoStuff
into Thing<TEntity>
, like for instance casting object
. Thanks to @Charleh I realised I was tackling the problem wrong and the solution was simply to implement both the class and interface separately like so:
public class Request : GenericClass<TEntity>, IThingRequest<Entity>
{ }
Upvotes: 1
Reputation: 565
I see following variant of solution. GenericClass should implement IThingRequest. Then DoStuff extension method can be made reflectively recursive:
using System;
using System.Reflection;
namespace ConsoleApp1
{
static class Program
{
static void Main(string[] args)
{
var request = new Request();
var result = request.DoStuff();
Console.ReadKey();
}
private static MethodInfo _doStaffMethodInfo;
public static MethodInfo DoStaffMethodInfo => _doStaffMethodInfo = _doStaffMethodInfo ?? typeof(Program).GetMethod("DoStuff");
public static object DoStuff<TEntity>(this IThingRequest<TEntity> request)
{
Type underlyingTypeOfTEntity = typeof(TEntity).GetInterface("IThingRequest`1")?.GenericTypeArguments[0];
if (underlyingTypeOfTEntity != null)
{
MethodInfo doStaffMethodInfo = DoStaffMethodInfo.MakeGenericMethod(underlyingTypeOfTEntity);
object thingRequest = Activator.CreateInstance(typeof(ThingRequest<>).MakeGenericType(underlyingTypeOfTEntity));
return doStaffMethodInfo.Invoke(null, new []{thingRequest});
}
else
{
return new Thing<TEntity>();
}
}
}
public interface IThingRequest<TEntity>
{
}
public class GenericClass<TEntity> : IThingRequest<TEntity>
{
}
public class Thing<TEntity>
{
}
public class ThingRequest<TEntity> : IThingRequest<TEntity>
{
}
public class Request : IThingRequest<GenericClass<Entity>>
{ }
public class Entity
{
}
}
Upvotes: 0
Reputation: 142038
If you want to handle nested generics and you know "wrapper" one you need to something like this:
public static Thing<T2> UnWrap<T1, T2>(IThingRequest<T1> request)
where T1: GenericClass<T2>
=> new Thing<T2>();
Upvotes: 0