【问题标题】:Extension method that returns underlying type of generic argument返回泛型参数的基础类型的扩展方法
【发布时间】:2020-05-01 08:06:37
【问题描述】:

我正在尝试编写IThingRequest<TEntity> 的扩展方法,它返回Thing<TEntity>。我希望该方法只返回 TEntity 的底层类型,而不是它会实现的任何其他泛型类或接口。因此,在下面的示例中,希望返回类型应该是 Thing<Entity> 而不是 Thing<GenericClass<Entity>>

扩展方法:

public static Thing<TEntity> DoStuff<TEntity>(IThingRequest<TEntity> request)
    => new Thing<TEntity>();

调用扩展方法:

public class Request : IThingRequest<GenericClass<Entity>>
{ }

var request = new Request();
var result = request.DoStuff();

结果类型现在是Thing&lt;GenericClass&lt;Entity&gt;&gt;

我的第一反应是where 有办法实现这一点,但我想不通。我也考虑过使用反射来获取TEntity 的非泛型类型并返回Thing&lt;object&gt;,但我认为这需要在使用DoStuff 方法的地方进行转换。

非常感谢任何帮助!

【问题讨论】:

  • 传入泛型类时为什么要返回非泛型类?您能否展示一些具有某些上下文的示例代码,以便帮助人们理解内容和原因?我在某种程度上明白你的要求,但你想用这个解决什么,也许有更好的模式?
  • return 语句在表达式体方法中不需要,请发布您的实际代码,当前不会编译
  • 谢谢,错过了,删除了退货!
  • 你说得对@Charleh,我在想这个错误,而不是让Request 实现IThingRequest&lt;GenericClass&lt;Entity&gt;&gt; 我改为分别实现GenericClass&lt;Entity&gt;, IThingRequest&lt;Entity&gt;

标签: c# generics extension-methods


【解决方案1】:

感谢大家的意见!

我想要一个解决方案,我不必将结果从 DoStuff 转换为 Thing&lt;TEntity&gt;,例如转换 object。感谢@Charleh,我意识到我解决的问题是错误的,解决方案就是像这样分别实现类和接口:

public class Request : GenericClass<TEntity>, IThingRequest<Entity>
{ }

【讨论】:

  • 这看起来更有意义,很高兴你解决了问题,有时你只需要退后一步,从另一个角度来看!
【解决方案2】:

如果你想处理嵌套泛型并且你知道“包装器”,你需要这样的东西:

public static Thing<T2> UnWrap<T1, T2>(IThingRequest<T1> request) 
       where T1: GenericClass<T2>
=> new Thing<T2>();

【讨论】:

    【解决方案3】:

    我看到以下解决方案的变体。 GenericClass 应该实现 IThingRequest。然后可以使 DoStuff 扩展方法反射递归:

    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
        {
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-09-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多