在ASP.NET Core上,我具有以下模型:
public class Model {
public Filter<Int32> filter { get; set; }
}
以下是过滤器:
public class Filter<T> {
public T Value { get; set; }
public Filter(T value) {
Value = value;
}
}
public static class Filter {
public static Boolean TryParse<T>(String value, out Filter<T> filter) {
// Try parse code
}
}
我需要创建一个ModelBinder来绑定Filter类型的属性:
public class FilterModelBinder : IModelBinder {
public Task BindModelAsync(ModelBindingContext bindingContext) {
if (bindingContext == null)
throw new ArgumentNullException(nameof(bindingContext));
String modelName = bindingContext.ModelName;
ValueProviderResult valueProviderResult = bindingContext.ValueProvider.GetValue(modelName);
if (valueProviderResult == ValueProviderResult.None)
return Task.CompletedTask;
bindingContext.ModelState.SetModelValue(modelName, valueProviderResult);
String value = valueProviderResult.FirstValue;
if (String.IsNullOrEmpty(value))
return Task.CompletedTask;
if (!Filter.TryParse(value, out Filter<T> filter)) {
bindingContext.ModelState.TryAddModelError(modelName, "Value is not of type Filter");
return Task.CompletedTask;
}
bindingContext.Result = ModelBindingResult.Success(filter);
return Task.CompletedTask;
}
}
我的问题是如何将TryParse应用于通用过滤器:
Filter.TryParse(value, out Filter<T> filter)
如何在ModelBinder中使用泛型类型?
答案 0 :(得分:0)
解决方案1
使用反射调用TryParse
public class FilterModelBinder : IModelBinder
{
public Task BindModelAsync(ModelBindingContext bindingContext)
{
//same binder code
//get filter generic type
Type filterType = bindingContext.ModelType.GenericTypeArguments.Single();
if (!TryGetFilter(value, filterType, out object filter))
{
bindingContext.ModelState.TryAddModelError(modelName, "Value is not of type Filter");
return Task.CompletedTask;
}
bindingContext.Result = ModelBindingResult.Success(filter);
return Task.CompletedTask;
}
private bool TryGetFilter(string value, Type filterType, out object filter)
{
var parameters = new object[] { value, null };
bool result = (bool)typeof(Filter)
.GetMethod(nameof(Filter.TryParse))
.MakeGenericMethod(filterType)
.Invoke(null, parameters);
filter = parameters[1]; //out parameter is placed here
return result;
}
}
解决方案2
介绍接受过滤器类型的TryParse
的非通用版本
public static class Filter
{
public static bool TryParse<T>(string value, out Filter<T> filter)
{
bool result = TryParse(value, typeof(T), out object innerFilter);
filter = (Filter<T>)innerFilter;
return result;
}
public static bool TryParse(string value, Type type, out object filter)
{
//parse logic here
}
}
并在模型活页夹中调用它
//same binder code
//get filter generic type
Type filterType = bindingContext.ModelType.GenericTypeArguments.Single();
if (!Filter.TryParse(value, filterType, out object filter))
{
bindingContext.ModelState.TryAddModelError(modelName, "Value is not of type Filter");
return Task.CompletedTask;
}
//same binder code