如何在上下文中动态指定方法的泛型类型(如果可能,不使用反射)
c#
那么是否可以在 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
}
现在我的问题是我将提供一个string“foo”,internal class Foo因为它Foo是内部的,不能被我的其他项目访问(这是预期的)。但它在外部被称为string“foo”。
现在我想调用以下方法(这是公共的)。
public async Task<IEnumerable<WhateverClass>> GetItemsFor(string forAsString, int entityId, int itemId, params string[] keys)
{
var forAsType = forAsString switch
{
"foo" => typeof(Foo) // or what is needed here
};
return await _myRepository.GetItemsFor<forAsType>(entityId, itemId, keys); // this is not possible. How can I make this work?
}
因为泛型T正在访问 aDbSet类型,T所以我需要能够在上下文中提供它。
那么我该如何解决这个难题呢?反射不是被禁止的,但我想知道是否有一种“本地”方式。或者一种值得尊敬的反思方式
编辑1:
WhateverClass有相关性IEntity。假设我想设置一个bool基于是否IEntity在集合中。这个抽象了很多,但是在这里把所有的上下文都打出来是没有用的。
public class WhateverClass
{
public bool Enabled { get; set }
}
回答
一种选择是使用从 switch 表达式调用的通用方法。为简洁起见,这可以是嵌套方法。这样既可以避免重复,也可以避免反思。例如:
public Task<IEnumerable<WhateverClass>> GetItemsFor(
string forAsString, int entityId, int itemId, params string[] keys)
{
return forAsString switch
{
"foo" => Impl<Foo>(),
"bar" => Impl<Bar>(),
_ => throw new ArgumentException($"Unknown 'for' value: {forAsString}");
};
async Task<IEnumerable<WhateverClass>> Impl<T>() =>
await _myRepository.GetItemsFor<T>(entityId, itemId, keys);
}
您仍然需要 switch 表达式,但它可能比使用反射更好。
- @Roy: Why would it not work as I typed it? (I had a small typo on the return type of the method, but otherwise I'd expect it to work...) In general, any time you say something doesn't work, it's worth providing details (e.g. compilation error, exception etc). Otherwise the obvious next question is pretty much always going to be asking for details.