Это сложно. FindAction вызывается для ControllerActionInvoker. Это в конечном итоге вызывает ReflectedControllerDescriptor.FindAction, который, в свою очередь, вызывает ActionMethodSelector.FindActionMethod, который вызывает RunSelectionFilters для того же типа. Этот метод берет список методов, переданных ему воротником, и повторяет их, изучая аргументы каждого метода и сравнивая их со значениями в запросе. Поскольку это должно выполняться быстро при поступлении запроса, все это кэшируется, и поскольку он предназначен для расширения, между уровнями, которые я описал, есть несколько абстрактных типов. Следовательно, поначалу может быть немного трудно следовать, и, вероятно, было бы трудно повторно использовать его для логики, не связанной с контроллером. Тем не менее, вы можете использовать его в качестве модели для реализации своей собственной системы. Я думаю, что это слишком сложно для доменного приложения. Число точек расширения, вероятно, подходит для инфраструктуры MVC, но для вашего собственного кода YAGNI.
Я надеюсь, что этого достаточно для начала.
Что касается использования связывателя модели без веб-стека: ну, вам все еще нужен MVC, но не обязательно веб-сервер. Вот как мы это делаем в модульном тесте:
internal static T Bind<T>(string prefix, FormCollection collection, ModelStateDictionary modelState) where T:BaseTimeRecordPresentationModel
{
var mbc = new ModelBindingContext()
{
ModelName = prefix,
ModelState = modelState,
ModelType = typeof(T),
ValueProvider = collection.ToValueProvider()
};
IModelBinder binder = new TimeRecordModelBinder();
var cc = new ControllerContext();
return binder.BindModel(cc, mbc) as T;
}
internal static T BindAndAssertValid<T>(string prefix, FormCollection collection) where T:BaseTimeRecordPresentationModel
{
var msd = new ModelStateDictionary();
var result = Bind<T>(prefix, collection, msd);
if (!msd.IsValid)
{
Assert.Fail(ModelStateValidationSummary(msd));
}
return result;
}