소스 오픈 - ASP를 읽어드릴게요.NET_MVC(13)
연결이 원활하기 위해서 전편의 마지막 코드를 다시 한 번 붙여라. 우선 코드 단락 1이라고 부른다.
protected virtual objectGetParameterValue(ControllerContext controllerContext, ParameterDescriptorparameterDescriptor)
{
// collect all of the necessarybinding properties
Type parameterType =parameterDescriptor.ParameterType;
IModelBinder binder =GetModelBinder(parameterDescriptor);
IValueProvider valueProvider =controllerContext.Controller.ValueProvider;
string parameterName =parameterDescriptor.BindingInfo.Prefix ?? parameterDescriptor.ParameterName;
Predicate<string>propertyFilter = GetPropertyFilter(parameterDescriptor);
// finally, call into the binder
ModelBindingContext bindingContext= new ModelBindingContext()
{
FallbackToEmptyPrefix =(parameterDescriptor.BindingInfo.Prefix == null), // only fall back if prefixnot specified
ModelMetadata =ModelMetadataProviders.Current.GetMetadataForType(null, parameterType),
ModelName = parameterName,
ModelState =controllerContext.Controller.ViewData.ModelState,
PropertyFilter =propertyFilter,
ValueProvider = valueProvider
};
object result =binder.BindModel(controllerContext, bindingContext);
return result ??parameterDescriptor.DefaultValue;
}
코드 세그먼트 1
여기서 관건은 두 가지를 분명히 해야 한다. 첫째, MVC가 IModel Binder 인터페이스의 실례를 어떻게 얻는가, 둘째, 이 인터페이스의 Bind Model 방법은 Request 관련 정보를 상응하는 모델 위에 어떻게 연결하는가이다.
첫 번째 점을 보고 코드 세그먼트 1에서 GetModelBinder 방법의 호출을 찾아 F12를 누르면 정의에 들어갑니다(코드 세그먼트 2).이 방법은'//look on the parameter itself, then look in the global table'이라는 주석과 결합하면 MVC가 먼저 들어오는parameter Descriptor를 검사한다는 것을 알 수 있다.BindingInfo.Binder가 비어 있는지 여부, 비어 있지 않으면 이 속성을 되돌려줍니다. 비어 있으면 Binders를 호출합니다.GetBinder 메서드, 글로벌 테이블에서 IModelBinder를 찾습니다.
private IModelBinderGetModelBinder(ParameterDescriptor parameterDescriptor)
{
// look on the parameter itself,then look in the global table
returnparameterDescriptor.BindingInfo.Binder ?? Binders.GetBinder(parameterDescriptor.ParameterType);
}
코드 세그먼트 2
Binders로 들어가기GetBinder 메서드의 정의입니다. 리셋이 많아서 최종 호출된 버전 (코드 세그먼트 3) 을 직접 찾을 수 있습니다.
private IModelBinder GetBinder(TypemodelType, IModelBinder fallbackBinder)
{
// Try to look up a binder for thistype. We use this order of precedence:
// 1. Binder returned from provider
// 2. Binder registered in theglobal table
// 3. Binder attribute defined onthe type
// 4. Supplied fallback binder
IModelBinder binder =_modelBinderProviders.GetBinder(modelType);
if (binder != null)
{
return binder;
}
if(_innerDictionary.TryGetValue(modelType, out binder))
{
return binder;
}
// Function is called frequently,so ensure the error delegate is stateless
binder =ModelBinders.GetBinderFromAttributes(modelType, (Type errorModel) =>
{
throw new InvalidOperationException(
String.Format(CultureInfo.CurrentCulture,MvcResources.ModelBinderDictionary_MultipleAttributes, errorModel.FullName));
});
return binder ?? fallbackBinder;
}
코드 세그먼트 3
마이크로소프트의 소스 오픈 프로젝트 그룹은 여전히 코드 주석을 비교적 중시하는데, 이 방법은 처음에 상당히 깔끔한 주석이었다.비록 여러분의 영어는 모두 상당한 NB이지만, 저는 추태를 보여 번역을 하겠습니다.
이 종류의binder를 찾아보십시오.다음과 같은 순서로 검색했습니다.
1. provider가 반환하는 Binder
2. 글로벌 리스트에 등록된 Binder
3. 이 유형에 정의된 Binder 특성
4. 사용자가 제공하는 예비 Binder
다음은 이 네 개의 실현 원리를 조목조목 토론한다.
1. provider가 반환하는 Binder.
다음 문을 찾습니다.
IModelBinderbinder = _modelBinderProviders.GetBinder(modelType);
모델 Binder Providers라는 개인 구성원이 어떻게 값을 부여하는지 보고, 그 클래스인 모델 Binder Dictionary의 구조 함수 (코드 세그먼트 4) 를 찾아봅시다.
public ModelBinderDictionary()
:this(ModelBinderProviders.BinderProviders)
{
}
internal ModelBinderDictionary(ModelBinderProviderCollectionmodelBinderProviders)
{
_modelBinderProviders =modelBinderProviders;
}
코드 세그먼트 4
모델 Binder Providers는 모델 Binder Providers를 사용합니다.BinderProviders는 값을 부여하고 ModelBinderProviders는 값을 부여합니다.Binder Providers[1]는 또 뭐죠?우리는 코드 세그먼트 5를 보았는데, 이것은 우리가 자신의 MVC 프로젝트에서 글로벌한 것이다.asax 파일의 Application이 방법 중 두 번째 문장(//*곳)은 우리가 사용자 정의의 mModel Binder Provider를 Model Binder Provider에 추가하는 것이다.Binder Providers 집합에서 이 집합은 위에 표시된 [1] 곳의 그 어떤 것이다.
protected voidApplication_Start()
{
AreaRegistration.RegisterAllAreas();
ModelBinderProviders.BinderProviders.Add(newCustomModelBinderProvider());//*
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
}
코드 세그먼트 5
2. 글로벌 리스트에 등록된 Binder.
이것은 비교적 간단합니다. 코드 [innerDictionary.TryGetValue(modelType,out binder)]입니다. 그 중에서 innerDictionary는 사전의 대상입니다. 이 사전에서 이 유형의 Binder를 찾는 것을 의미합니다.
3. 이 유형에 정의된 Binder 특성.
코드 세그먼트 3에서 ModelBinders를 찾습니다.GetBinder From Attributes 방법은 이름에서 Attributes에서 Binder를 가져오는 역할을 추측할 수 있습니다.다음은 정의 (코드 세그먼트 6) 로 이동합니다. 이 코드는 GetAttributes () 를 통해 형식 type의 모든 특성 (Attributes) 을 가져오고, Single OfType Default OrError 방법을 호출하여 사용자 정의의Custom Model Binder Attribute를 가져오고, 마지막으로 GetBinder 방법을 호출하여 IMode Binder를 가져와서 되돌려줍니다.
internal static IModelBinder GetBinderFromAttributes(Type type,Action<Type> errorAction)
{
AttributeList allAttrs = newAttributeList(TypeDescriptorHelper.Get(type).GetAttributes());
CustomModelBinderAttributebinder = allAttrs.SingleOfTypeDefaultOrError<Attribute,CustomModelBinderAttribute, Type>(errorAction, type);
return binder == null ? null : binder.GetBinder();
}
코드 세그먼트 6
Single OfType Default OrError 방법의 정의는 코드 세그먼트 7을 보십시오. 이것은 IList
/// <summary>
/// Returns a single value in list matching type TMatch if there is onlyone, null if there are none of type TMatch or calls the
/// errorAction with errorArg1 if there is more than one.
/// </summary>
public static TMatch SingleOfTypeDefaultOrError<TInput, TMatch,TArg1>(this IList<TInput> list, Action<TArg1> errorAction, TArg1errorArg1) where TMatch : class
{
Contract.Assert(list != null);
Contract.Assert(errorAction != null);
TMatch result = null;
for (int i = 0; i < list.Count; i++)
{
TMatch typedValue = list[i] asTMatch;
if (typedValue != null)
{
if (result == null)
{
result = typedValue;
}
else
{
errorAction(errorArg1);
return null;
}
}
}
return result;
}
코드 세그먼트 7
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
클린 아키텍처의 Presenter를 이해하기 어려운 것은 MVC 2가 아니기 때문에클린 아키텍처에는 구체적인 클래스 구성 예를 보여주는 다음 그림이 있습니다. 이 그림 중에서 Presenter와 Output Boundary(Presenter의 인터페이스)만 구체 구현을 이미지하는 것이 매우 어렵다...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.