在 C# 中,是否可以创建和应用实例方法字典?
In C#, is it possible to create and apply a Dictionary of instance methods?
我目前有以下方法:
private FilterDefinition<BsonDocument> BuildFilters(GenericQueryParameters parameters)
{
FilterDefinitionBuilder<BsonDocument> filterBuilder = Builders<BsonDocument>.Filter;
FilterDefinition<BsonDocument> filters = filterBuilder.Empty;
foreach (string filterString in parameters.Filters)
{
Match match = Regex.Match(filterString, @"(\w+)\s*([<>=]+)\s*(.*)", RegexOptions.IgnoreCase);
if (match.Success)
{
string fieldName = match.Groups[1].Value;
string condition = match.Groups[2].Value;
string targetValue = match.Groups[3].Value;
if ("==".Equals(condition))
{
filters = filters & filterBuilder.Eq(fieldName, targetValue);
}
else if ("!=".Equals(condition))
{
filters = filters & filterBuilder.Ne(fieldName, targetValue);
}
else if ("<=".Equals(condition))
{
filters = filters & filterBuilder.Lte(fieldName, targetValue);
}
else if ("<".Equals(condition))
{
filters = filters & filterBuilder.Lt(fieldName, targetValue);
}
else if (">=".Equals(condition))
{
filters = filters & filterBuilder.Gte(fieldName, targetValue);
}
else if (">".Equals(condition))
{
filters = filters & filterBuilder.Gt(fieldName, targetValue);
}
else
{
throw new MalformedDatabaseFilterException($"The condition {condition} could not be applied.");
}
}
else
{
throw new MalformedDatabaseFilterException($"The filter {filterString} could not be parsed.");
}
}
return filters;
}
这可行,但它很长且重复。
我想让它更像是:
private static readonly Dictionary<string, Action> FilterBySymbols = new Dictionary<string, Action>() {
{"==", FilterDefinitionBuilder<BsonDocument>.Eq },
{"!=", FilterDefinitionBuilder<BsonDocument>.Ne },
{"<=", FilterDefinitionBuilder<BsonDocument>.Lte },
{"<", FilterDefinitionBuilder<BsonDocument>.Lt },
{">=", FilterDefinitionBuilder<BsonDocument>.Gte },
{">", FilterDefinitionBuilder<BsonDocument>.Gt }
};
private FilterDefinition<BsonDocument> BuildFilters(GenericQueryParameters parameters)
{
FilterDefinitionBuilder<BsonDocument> filterBuilder = Builders<BsonDocument>.Filter;
FilterDefinition<BsonDocument> filters = filterBuilder.Empty;
foreach (string filterString in parameters.Filters)
{
Match match = Regex.Match(filterString, @"(\w+)\s*([<>=]+)\s*(.*)", RegexOptions.IgnoreCase);
if (match.Success)
{
string fieldName = match.Groups[1].Value;
string condition = match.Groups[2].Value;
string targetValue = match.Groups[3].Value;
if (FilterBySymbols.TryGetValue(condition, out Action action))
{
filters = filters & action(fieldName, targetValue);
}
else
{
throw new MalformedDatabaseFilterException($"The condition {condition} could not be applied.");
}
}
else
{
throw new MalformedDatabaseFilterException($"The filter {filterString} could not be parsed.");
}
}
return filters;
}
...但这不会编译,因为操作都是实例方法。
此外,一旦我从映射中获取方法,就会出现一个悬而未决的问题,即如何将其应用于实例。
有什么想法whether/how我可以使更高版本工作吗?
你可以有一个 Dictionary<string, Action<FilterDefinitionBuilder<BsonDocument>, string, string>>
。初始化为:
{ "==", (builder, fieldName, targetValue) => builder.Eq(fieldName, targetValue) },
{ "!=", (builder, fieldName, targetValue) => builder.Neq(fieldName, targetValue) }
并将其命名为:
if (FilterBySymbols.TryGetValue(condition, out Action action))
{
action(filterBuilder, fieldName, targetValue);
}
就是说,我可能会使用 switch 表达式来编写它:这样会更清晰也更便宜:
filters = filters & condition switch
{
"==" => filterBuilder.Eq(fieldName, targetValue),
"!=" => filterBuilder.Neq(fieldName, targetValue),
...
_ => throw new MalformedDatabaseFilterException($"The condition {condition} could not be applied.");
}
我目前有以下方法:
private FilterDefinition<BsonDocument> BuildFilters(GenericQueryParameters parameters)
{
FilterDefinitionBuilder<BsonDocument> filterBuilder = Builders<BsonDocument>.Filter;
FilterDefinition<BsonDocument> filters = filterBuilder.Empty;
foreach (string filterString in parameters.Filters)
{
Match match = Regex.Match(filterString, @"(\w+)\s*([<>=]+)\s*(.*)", RegexOptions.IgnoreCase);
if (match.Success)
{
string fieldName = match.Groups[1].Value;
string condition = match.Groups[2].Value;
string targetValue = match.Groups[3].Value;
if ("==".Equals(condition))
{
filters = filters & filterBuilder.Eq(fieldName, targetValue);
}
else if ("!=".Equals(condition))
{
filters = filters & filterBuilder.Ne(fieldName, targetValue);
}
else if ("<=".Equals(condition))
{
filters = filters & filterBuilder.Lte(fieldName, targetValue);
}
else if ("<".Equals(condition))
{
filters = filters & filterBuilder.Lt(fieldName, targetValue);
}
else if (">=".Equals(condition))
{
filters = filters & filterBuilder.Gte(fieldName, targetValue);
}
else if (">".Equals(condition))
{
filters = filters & filterBuilder.Gt(fieldName, targetValue);
}
else
{
throw new MalformedDatabaseFilterException($"The condition {condition} could not be applied.");
}
}
else
{
throw new MalformedDatabaseFilterException($"The filter {filterString} could not be parsed.");
}
}
return filters;
}
这可行,但它很长且重复。 我想让它更像是:
private static readonly Dictionary<string, Action> FilterBySymbols = new Dictionary<string, Action>() {
{"==", FilterDefinitionBuilder<BsonDocument>.Eq },
{"!=", FilterDefinitionBuilder<BsonDocument>.Ne },
{"<=", FilterDefinitionBuilder<BsonDocument>.Lte },
{"<", FilterDefinitionBuilder<BsonDocument>.Lt },
{">=", FilterDefinitionBuilder<BsonDocument>.Gte },
{">", FilterDefinitionBuilder<BsonDocument>.Gt }
};
private FilterDefinition<BsonDocument> BuildFilters(GenericQueryParameters parameters)
{
FilterDefinitionBuilder<BsonDocument> filterBuilder = Builders<BsonDocument>.Filter;
FilterDefinition<BsonDocument> filters = filterBuilder.Empty;
foreach (string filterString in parameters.Filters)
{
Match match = Regex.Match(filterString, @"(\w+)\s*([<>=]+)\s*(.*)", RegexOptions.IgnoreCase);
if (match.Success)
{
string fieldName = match.Groups[1].Value;
string condition = match.Groups[2].Value;
string targetValue = match.Groups[3].Value;
if (FilterBySymbols.TryGetValue(condition, out Action action))
{
filters = filters & action(fieldName, targetValue);
}
else
{
throw new MalformedDatabaseFilterException($"The condition {condition} could not be applied.");
}
}
else
{
throw new MalformedDatabaseFilterException($"The filter {filterString} could not be parsed.");
}
}
return filters;
}
...但这不会编译,因为操作都是实例方法。 此外,一旦我从映射中获取方法,就会出现一个悬而未决的问题,即如何将其应用于实例。
有什么想法whether/how我可以使更高版本工作吗?
你可以有一个 Dictionary<string, Action<FilterDefinitionBuilder<BsonDocument>, string, string>>
。初始化为:
{ "==", (builder, fieldName, targetValue) => builder.Eq(fieldName, targetValue) },
{ "!=", (builder, fieldName, targetValue) => builder.Neq(fieldName, targetValue) }
并将其命名为:
if (FilterBySymbols.TryGetValue(condition, out Action action))
{
action(filterBuilder, fieldName, targetValue);
}
就是说,我可能会使用 switch 表达式来编写它:这样会更清晰也更便宜:
filters = filters & condition switch
{
"==" => filterBuilder.Eq(fieldName, targetValue),
"!=" => filterBuilder.Neq(fieldName, targetValue),
...
_ => throw new MalformedDatabaseFilterException($"The condition {condition} could not be applied.");
}