嗯,除了 DTO,您还可以使用丰富的模型。您将需要一个自定义的模型绑定器,它将负责ctor 注入模型。
内置模型绑定器抱怨找不到默认 ctor。因此,您需要一个自定义的。
您可能会找到类似问题here 的解决方案,它会检查已注册的服务以创建模型。
请务必注意,下面的 sn-ps 提供的功能略有不同,希望能满足您的特定需求。下面的代码需要带有 ctor 注入的模型。当然,这些模型具有您可能已经定义的常用属性。这些属性的填充完全符合预期,因此使用 ctor 注入绑定模型时的正确行为。
public class DiModelBinder : ComplexTypeModelBinder
{
public DiModelBinder(IDictionary<ModelMetadata, IModelBinder> propertyBinders) : base(propertyBinders)
{
}
/// <summary>
/// Creates the model with one (or more) injected service(s).
/// </summary>
/// <param name="bindingContext"></param>
/// <returns></returns>
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;
}
}
以下是活页夹的注册方式:
services.AddMvc().AddMvcOptions(options =>
{
// replace ComplexTypeModelBinderProvider with its descendent - IoCModelBinderProvider
var provider = options.ModelBinderProviders.FirstOrDefault(x => x.GetType() == typeof(ComplexTypeModelBinderProvider));
var binderIndex = options.ModelBinderProviders.IndexOf(provider);
options.ModelBinderProviders.Remove(provider);
options.ModelBinderProviders.Insert(binderIndex, new DiModelBinderProvider());
});
我不太确定新的活页夹是否必须在同一索引处完全注册,您可以尝试一下。
最后,你可以这样使用它:
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
}
模型类由提供(已注册的)服务的绑定器创建,其余模型绑定器提供来自其常用来源的属性值。
HTH