C# 如何在上下文中动态地为方法指定泛型类型(如果可能的话,没有反射)

C# 如何在上下文中动态地为方法指定泛型类型(如果可能的话,没有反射),c#,generics,reflection,C#,Generics,Reflection,那么,是否可以在C#中为方法动态指定泛型类型?我说的不是使用反射,而是使用C 例如: internal class MyRepository { async Task<IEnumerable<WhateverClass>> GetItemsFor<T>(int entityId, int itemId, params string[] keys) where T : class, IEntity { // do whatever }

那么,是否可以在C#中为方法动态指定泛型类型?我说的不是使用反射,而是使用C

例如:

internal class MyRepository
{
  async Task<IEnumerable<WhateverClass>> GetItemsFor<T>(int entityId, int itemId, params string[] keys)
    where T : class, IEntity
  {
    // do whatever
  }
}

interface IEntity
{
  public int Id { get; set; }
}

internal class Foo : IEntity
{
  // whatever
}
因为泛型
T
正在访问
T
类型的
DbSet
,所以我需要能够在上下文中提供这一点

那么我该如何解决这个难题呢?反思是不被禁止的,但我想知道是否有一种“本土”的方式。或者是一种值得尊敬的思考方式

编辑1:
WhateverClass
entity
相关。假设我想根据
IEntity
是否在集合中设置
bool
。这被抽象了很多,但是在这里键入所有上下文是没有用的

public class WhateverClass
{
  public bool Enabled { get; set }
}

不,没有思考,这是不可能的。您需要使用反射来获取要调用的泛型方法的MethodInfo,然后使用.MakeGenericMethod()调用来应用“foo”类型并使用.Invoke()调用它

另外,这是返回一个枚举,具体是什么?如果foo是内部的,那么消费者会期望什么


我还认为您所做的完全违反了您所使用的存储库模式。使用者不需要知道它可以传递给方法的类型。存储库应该用于特定的数据集。

不,如果没有反射,这是不可能的。您需要使用反射来获取要调用的泛型方法的MethodInfo,然后使用.MakeGenericMethod()调用来应用“foo”类型并使用.Invoke()调用它

另外,这是返回一个枚举,具体是什么?如果foo是内部的,那么消费者会期望什么


我还认为您所做的完全违反了您所使用的存储库模式。使用者不需要知道它可以传递给方法的类型。存储库应该用于特定的数据集。

一个选项是使用从开关表达式调用的通用方法。为了简洁起见,可以使用嵌套方法。这样既可以避免重复,也可以避免反思。例如:

getItems的公共任务(
字符串,int-entityId,int-itemId,params字符串[]键)
{
回位串开关
{
“foo”=>Impl(),
“bar”=>Impl(),
_=>抛出新的ArgumentException($“Unknown”for“value:{forAsString}”);
};
异步任务Impl()=>
wait_myRepository.GetItemsFor(entityId、itemId、Key);
}

您仍然需要开关表达式,但它可能比使用反射更好。

一个选项是使用从开关表达式调用的通用方法。为了简洁起见,可以使用嵌套方法。这样既可以避免重复,也可以避免反思。例如:

getItems的公共任务(
字符串,int-entityId,int-itemId,params字符串[]键)
{
回位串开关
{
“foo”=>Impl(),
“bar”=>Impl(),
_=>抛出新的ArgumentException($“Unknown”for“value:{forAsString}”);
};
异步任务Impl()=>
wait_myRepository.GetItemsFor(entityId、itemId、Key);
}

您仍然需要switch表达式,但它可能比使用反射更好。

这里什么是
WhateverClass
?这是否也取决于的
?(如果以“foo”作为第一个参数调用,您是否希望它返回一个
任务
?@jonsket no whates是一个与
IEntity
相关的公共类。但是因为
Foo
是内部的,我不能返回
IEnumerable
,因为这是不允许的
everclass
与“Foo”有什么关系?@Llama我认为这对这个问题不重要。在我的编辑中,我解释了这一点。@Llama是的,我不是唯一一个在这个项目上工作的人,很不幸,重构不会发生。如果这是我的个人项目,它会被创建得有点不同。所以问题是,“什么是值得尊敬的反射方式”这里什么是
WhateverClass
?这是否也取决于
?(如果以“foo”作为第一个参数调用,您是否希望它返回一个
任务
?@jonsket no whates是一个与
IEntity
相关的公共类。但是因为
Foo
是内部的,我不能返回
IEnumerable
,因为这是不允许的
everclass
与“Foo”有什么关系?@Llama我认为这对这个问题不重要。在我的编辑中,我解释了这一点。@Llama是的,我不是唯一一个在这个项目上工作的人,很不幸,重构不会发生。如果这是我的个人项目,它会被创建得有点不同。所以问题是,“什么是值得尊敬的反射方式”编辑了我的问题我的存储库是针对特定的数据集的。这种方法适用于我们数据库的高级过滤系统,其中过滤器可以应用于实体集合。谜题的最后一步是从我们的CMS链接到必须应用的实际过滤器。因为我们的数据层是内部的,所以我必须使用DTO。但我确实需要知道我得到的过滤器是针对哪个特定的
IEntity
。这就是
T
编辑的内容我的问题我的存储库是针对特定数据集的。这种方法适用于我们数据库的高级过滤系统,其中过滤器可以应用于实体集合。谜题的最后一步是从我们的CMS链接到必须应用的实际过滤器。因为我们的数据层是内部的,所以我必须使用DTO。但我确实需要知道我得到的过滤器是针对哪个特定的
IEntity
。这就是
T
的作用,我喜欢你的方法,但不会像你键入的那样工作。我采纳了你的想法,得到了一个有效的版本。需要将开关的输出存储在<代码中
public class WhateverClass
{
  public bool Enabled { get; set }
}