除了DTO之外,您还可以使用丰富的模型。您需要一个定制的模型绑定器,它将负责将构造函数注入模型中。
内置的模型绑定器抱怨找不到默认构造函数。因此,您需要自定义一个。
您可以在
这里找到类似问题的解决方案,该方案检查注册的服务以创建模型。
值得注意的是,下面的代码片段提供略有不同的功能,希望能满足您的特定需求。以下代码期望具有构造函数注入的模型。当然,这些模型具有您可能定义的常规属性。这些属性被填充,正如预期的那样,所以好处是在绑定具有构造函数注入的模型时获得正确的行为。
public class DiModelBinder : ComplexTypeModelBinder
{
public DiModelBinder(IDictionary<ModelMetadata, IModelBinder> propertyBinders) : base(propertyBinders)
{
}
protected override object CreateModel(ModelBindingContext bindingContext)
{
var services = bindingContext.HttpContext.RequestServices;
var modelType = bindingContext.ModelType;
var ctors = modelType.GetConstructors();
foreach (var ctor in ctors)
{
var paramTypes = ctor.GetParameters().Select(p => p.ParameterType).ToList();
var parameters = paramTypes.Select(p => services.GetService(p)).ToArray();
if (parameters.All(p => p != null))
{
var model = ctor.Invoke(parameters);
return model;
}
}
return null;
}
}
这个文件夹将由以下提供:
public class DiModelBinderProvider : IModelBinderProvider
{
public IModelBinder GetBinder(ModelBinderProviderContext context)
{
if (context == null) { throw new ArgumentNullException(nameof(context)); }
if (context.Metadata.IsComplexType && !context.Metadata.IsCollectionType)
{
var propertyBinders = context.Metadata.Properties.ToDictionary(property => property, context.CreateBinder);
return new DiModelBinder(propertyBinders);
}
return null;
}
}
Here's how the binder would be registered:
services.AddMvc().AddMvcOptions(options =>
);
我不确定新的binder是否必须在完全相同的索引处注册,您可以进行实验。
最后,这是您如何使用它:
public class MyModel
{
private readonly IMyRepository repo;
public MyModel(IMyRepository repo)
{
this.repo = repo;
}
... do whatever you want with your repo
public string AProperty { get; set; }
... other properties here
}
模型类由提供(已注册)服务的绑定器创建,其余的模型绑定器从它们通常的来源提供属性值。
希望这有帮助。