Is it possible to have a non-public parameterless constructor that can be used for model binding?

天涯浪子 提交于 2020-01-11 12:27:50

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!