gpt4 book ai didi

c# - 如何创建不同类型的 Expression> 的集中提供者?

转载 作者:行者123 更新时间:2023-11-30 21:28:36 25 4
gpt4 key购买 nike

我为 ASP.NET Core 2.2 Web 应用程序编写了排序逻辑。我的概念是定义一个包含排序规则的字典。字典有string键。每个规则都与实体类型相关联。也有可能通过 string 检索特定类型实体的排序规则。 key 。

我写的排序逻辑不排序任何集合,它只存储和提供排序所需的信息。每个排序规则都有:

  • 一个Expression<Func<T, object>> ;
  • 一个bool描述排序方式的标志(升序/降序);
  • 一个bool指示特定排序规则是否为默认规则的标志。

我在 ISortOrderRule<T> 中定义了该数据接口(interface):

public interface ISortOrderRule<T>
{
Expression<Func<T, object>> Expression { get; }
bool IsDescending { get; }
bool IsDefault { get; }
}

SortOrderRule<T> 中默认实现类:

public class SortOrderRule<T> : ISortOrderRule<T>
{
public Expression<Func<T, object>> Expression { get; set; }
public bool IsDefault { get; set; }
public bool IsDescending { get; set; }
}

表达式可以用作例如 OrderBy() 的参数LINQ 方法。 IsDefault如果没有找到其他选项,可以在回退机制中使用标志以默认排序顺序。

现在,为了为特定实体创建排序规则,我创建了一个通用接口(interface) ISortOrderCollection<T>其中排序规则可以存储在底层字典中:

public interface ISortOrderCollection<T> :
IReadOnlyDictionary<string, ISortOrderRule<T>>,
IReadOnlyCollection<KeyValuePair<string, ISortOrderRule<T>>>,
IEnumerable<KeyValuePair<string, ISortOrderRule<T>>>,
IEnumerable
{

}

只读因为我希望它对外界关闭但对派生自 SortOrderCollectionBase<T> 的类开放:

public abstract class SortOrderCollectionBase<T> : ISortOrderCollection<T>
{
private readonly IDictionary<string, ISortOrderRule<T>> _rules;

public SortOrderCollectionBase()
{
_rules = new Dictionary<string, ISortOrderRule<T>>();
}

protected void AddSortOrderRule(string key, ISortOrderRule<T> sortOrderRule)
{
// Tweak over the key, add prefix or suffix depending on sorting way
// So sort order rules for the same property but with opposite
// sorting way can be distinguished.
var sortRuleKey = BuildSortOrderRuleKey(key, sortOrderRule);

_rules.Add(sortRuleKey, sortOrderRule);
}

// Implementations of interface members removed for brevity.
}

现在我可以为 Level 添加一些排序规则实体:

public class LevelSortOrderCollection : SortOrderCollectionBase<Level>
{
public LevelSortOrderCollection()
{
AddSortOrderRule(nameof(Level.Position), new SortOrderRule<Level>
{
Expression = (level) => level.Position,
IsDefault = true,
});
AddSortOrderRule(nameof(Level.Position), new SortOrderRule<Level>
{
Expression = (level) => level.Position,
IsDescending = true,
});
}
}

关卡模型:

public class Level
{
public int Id { get; set; }
public int Position { get; set; }
}

类型实现 ISortOrderCollection<T>注册于 StartupConfigureServices()方法:

services.AddScoped<ISortOrderCollection<Level>, LevelSortOrderCollection>();
// ...

最后我可以在 Controller 中使用排序顺序集合:

public class LevelsController : Controller
{
private readonly IRepository<Level> _levelsRepository;
private readonly ISortOrderCollection<Level> _levelSortOrder;

public LevelsController(
IRepository<Level> levelsRepository,
ISortOrderCollection<Level> levelSortOrder)
{
_levelsRepository = levelsRepository;
_levelSortOrder = levelSortOrder;
}

public async Task<IActionResult> Index(string sort)
{
var sortOrder = _levelSortOrder[sort];
var result = await _levelsRepository.GetPageAsync(sortOrder.Expression);

return View(result);
}
}

GetPageAsync()IRepository<Level>接受一个表达式,该表达式稍后用于使用 OrderBy() 对记录进行排序.

注意,我故意删除了一些 IMO 代码,没有带来任何值得放在这里的东西,比如空检查、验证、 Controller /存储库逻辑选择是否调用 OrderBy()OrderByDescending()并回退到默认排序顺序。如果您觉得需要查看更多内容,请在评论中告诉我。

问题

如何创建一个集中式排序顺序规则提供程序,可以访问多个实体的许多排序顺序集合?我不想直接为 Controller 中的特定实体类型注入(inject)排序顺序集合,而是希望能够注入(inject)通用排序顺序提供程序,如下所示:

private readonly IRepository<Level> _levelsRepository;
private readonly ISortOrderProvider _sortOrderProvider;

public LevelsController(
IRepository<Level> levelsRepository,
ISortOrderProvider sortOrderProvider)
{
_levelsRepository = levelsRepository;
_sortOrderProvider = sortOrderProvider;
}

然后我会用类型参数调用某种方法:

var sortOrder = _provider.GetSortOrderRule<Level>("Position");

这将尝试为在具有匹配 string 的类型参数中传递的实体类型找到排序顺序规则键。

最后的说明

我知道这一切都非常复杂,因此很有可能采用完全不同的方式来实现我想要做的事情。我对那种答案并不封闭。

最佳答案

首先,我建议您不要在 ISortOrderCollection<T> 中实现所有这些字典接口(interface)。 .虽然使该集合成为实际集合对您来说可能有意义,但实际上并没有太多好处:毕竟,您主要是通过键添加项目或检索项目。您实际上并不需要这些接口(interface)要求您实现的所有其他内容。相反,使用一个只涵盖您实际需要的小接口(interface),并使用组合来实现它。这也使测试更容易。

所以你是说你想要一个单一的提供者来保存所有类型的所有排序顺序表达式。首先考虑您希望如何使用它,然后构建一个提供必要 API 的接口(interface):

public interface ISortOrderProvider
{
void Add<T>(string name, ISortOrderRule<T> sortOrderRule);

ISortOrderRule<T> Get<T>(string name);

ISortOrderRule<T> GetDefault<T>();
}

好的,如果您查看它,您会注意到现在实际上有两个键:排序键和类型。因此,将两者都用作字典中的键。

现在,对于默认规则,有几种策略:您可以有一个单独的字典,只存储每种类型的默认规则;您还可以遍历所有规则,在您请求时查找默认值;或者您可以将默认规则存储在一个通用名称下,这样就可以直接查找它。我会选择后一种想法。

所以这是一个简单的示例实现:

public class SortOrderProvider : ISortOrderProvider
{
private const string DefaultKey = "__default";
private readonly Dictionary<(Type, string), object> _rules = new Dictionary<(System.Type, string), object>();

public void Add<T>(string name, ISortOrderRule<T> sortOrderRule)
{
_rules[(typeof(T), name)] = sortOrderRule;

if (sortOrderRule.IsDefault)
_rules[(typeof(T), DefaultKey)] = sortOrderRule;
}

public ISortOrderRule<T> Get<T>(string name)
{
if (_rules.TryGetValue((typeof(T), name), out var value))
return (ISortOrderRule<T>)value;
return GetDefault<T>();
}

public ISortOrderRule<T> GetDefault<T>()
{
if (_rules.TryGetValue((typeof(T), DefaultKey), out var value))
return (ISortOrderRule<T>)value;
else
return null;
}
}

关于c# - 如何创建不同类型的 Expression<Func<T, object>> 的集中提供者?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56264651/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com