C# 我可以将依赖项注入到使用.Net Core WebApi在post方法中创建的模型对象中吗?
如果在我的启动中,我已注册我的依赖项:C# 我可以将依赖项注入到使用.Net Core WebApi在post方法中创建的模型对象中吗?,c#,.net,asp.net-core-webapi,C#,.net,Asp.net Core Webapi,如果在我的启动中,我已注册我的依赖项: services.AddScoped<IService, SomeService>(); 我的模型课是这样的 public class Model { ... public Model(IService service) { ... } ... } 如果你想在模型中注入一些东西,你可以选择。在ModelBinder中,您可以使用所有注册的服务访问上下文,并且可以使用所需的任何参数调用模型的构造函数 一般来说,模型不应该引用正在使用它
services.AddScoped<IService, SomeService>();
我的模型课是这样的
public class Model {
...
public Model(IService service) { ... }
...
}
如果你想在模型中注入一些东西,你可以选择。在ModelBinder中,您可以使用所有注册的服务访问上下文,并且可以使用所需的任何参数调用模型的构造函数 一般来说,模型不应该引用正在使用它们的服务。所以,如果你真的想这样做,请仔细考虑。你可以为此创建一个。我们可以使用
ComplexTypeModelBinder
作为基础
public class ServiceModelBinder : ComplexTypeModelBinder
{
public ServiceModelBinder(IDictionary<ModelMetadata, IModelBinder> propertyBinders, ILoggerFactory loggerFactory)
: base(propertyBinders, loggerFactory)
{
}
public ServiceModelBinder(IDictionary<ModelMetadata, IModelBinder> propertyBinders, ILoggerFactory loggerFactory, bool allowValidatingTopLevelNodes) : base(propertyBinders, loggerFactory, allowValidatingTopLevelNodes)
{
}
protected override object CreateModel(ModelBindingContext bindingContext)
{
var modelTypeInfo = bindingContext.ModelType.GetTypeInfo();
//if type satisfies default binder requirements just use it
if (!modelTypeInfo.IsAbstract && modelTypeInfo.GetConstructor(Type.EmptyTypes) != null)
{
return base.CreateModel(bindingContext);
}
var constructors = modelTypeInfo.GetConstructors();
if (constructors.Length > 1)
{
throw new InvalidOperationException("Model should contain one constructor only");
}
var constructor = constructors.First();
var parameters = constructor.GetParameters();
//require that all parameters are marked with [FromServices]
//this step is completely optional
if (!parameters.Any(p => p.IsDefined(typeof(FromServicesAttribute))))
{
throw new InvalidOperationException("Mark all parameters with [FromServices]");
}
//build arguments from registered services
var arguments = parameters
.Select(p => bindingContext.ActionContext.HttpContext.RequestServices.GetService(p.ParameterType))
.ToArray();
return constructor.Invoke(arguments);
}
}
在领域驱动的设计中,模型不应该使用服务而不是相反的方式吗?具有状态但没有行为的模型将被视为贫血,因此在从JSON反序列化模型之后,下一步将是调用模型上的行为,这可能需要使用服务来完成其操作。这种依赖关系可以注入到模型上的方法中,但如果在模型实例化时这样做,对我来说会更干净。为什么不希望在模型中保留对服务的引用?
public class ServiceModelBinder : ComplexTypeModelBinder
{
public ServiceModelBinder(IDictionary<ModelMetadata, IModelBinder> propertyBinders, ILoggerFactory loggerFactory)
: base(propertyBinders, loggerFactory)
{
}
public ServiceModelBinder(IDictionary<ModelMetadata, IModelBinder> propertyBinders, ILoggerFactory loggerFactory, bool allowValidatingTopLevelNodes) : base(propertyBinders, loggerFactory, allowValidatingTopLevelNodes)
{
}
protected override object CreateModel(ModelBindingContext bindingContext)
{
var modelTypeInfo = bindingContext.ModelType.GetTypeInfo();
//if type satisfies default binder requirements just use it
if (!modelTypeInfo.IsAbstract && modelTypeInfo.GetConstructor(Type.EmptyTypes) != null)
{
return base.CreateModel(bindingContext);
}
var constructors = modelTypeInfo.GetConstructors();
if (constructors.Length > 1)
{
throw new InvalidOperationException("Model should contain one constructor only");
}
var constructor = constructors.First();
var parameters = constructor.GetParameters();
//require that all parameters are marked with [FromServices]
//this step is completely optional
if (!parameters.Any(p => p.IsDefined(typeof(FromServicesAttribute))))
{
throw new InvalidOperationException("Mark all parameters with [FromServices]");
}
//build arguments from registered services
var arguments = parameters
.Select(p => bindingContext.ActionContext.HttpContext.RequestServices.GetService(p.ParameterType))
.ToArray();
return constructor.Invoke(arguments);
}
}
public class ServiceModelBinderProvider : IModelBinderProvider
{
public IModelBinder GetBinder(ModelBinderProviderContext context)
{
if (context == null)
{
throw new ArgumentNullException(nameof(context));
}
if (context.Metadata.IsComplexType && !context.Metadata.IsCollectionType)
{
var propertyBinders = new Dictionary<ModelMetadata, IModelBinder>();
for (var i = 0; i < context.Metadata.Properties.Count; i++)
{
var property = context.Metadata.Properties[i];
propertyBinders.Add(property, context.CreateBinder(property));
}
var loggerFactory = context.Services.GetRequiredService<ILoggerFactory>();
return new ServiceModelBinder(
propertyBinders,
loggerFactory,
allowValidatingTopLevelNodes: true);
}
return null;
}
}
services
.AddControllersWithViews()
.AddMvcOptions(options =>
{
options.ModelBinderProviders.Insert(0, new ServiceModelBinderProvider());
})