问题
I have a following POCO class. I don not want the parameterless constructor to be public.
public class FileDownloadRequest
{
//public FileDownloadRequest() { }
public FileDownloadRequest(int fileId, RepositoryFolderTypes fileType) //RepositoryFolderTypes is an enum, not a class
{
this.FileId = fileId;
this.FileType = fileType;
}
public int FileId { get; set; }
public RepositoryFolderTypes FileType { get; set; } //an enum
}
When I am trying a https://10.27.8.6/Files/DownloadFile?fileId=1&folderType=SRC
request to the following controller action, I get an error saying that no parameterless constructor exists for this object.
[HttpGet]
public async Task<HttpResponseMessage> DownloadFile([FromUri] FileDownloadRequest request)
{
}
Is it possible to have a non-public constructor, or is a public one absolutely required?
回答1:
Yes, you can use any constructor you like, but you will have to do the model binding yourself then. The problem is in DefaultModelBinder.CreateModel
, which uses a parameterless public constructor.
You have to override the default model binder and create your own. If that is worth the time is up to you.
Steps to take:
- Override
CreateModel
; - Check the
modelType
for some generic constraint which models you need to call the constructor with parameters on; - Call Activator.CreateInstance(Type, Object[]) with the parameters. You could obtain their values from the
bindingContext
; - Register the model binder, either through the
ModelBinder
attribute, or globally.
Read more on custom bindings here.
回答2:
Also, while Patrick's answer is great and shows how to do it (in scenarios where this much effort really makes sense), I just add something I've noticed in another SO post.
Basically, mark the parameterless constructor as [Obsolete("Comment to indicate its for binding only")]
and that will prevent others from accidentally calling the parameterless one. (Thus showing explicitly which properties are required by the request object)
来源:https://stackoverflow.com/questions/44261895/is-it-possible-to-have-a-non-public-parameterless-constructor-that-can-be-used-f