솔루션은 여러 조금 고급 PostSharp 기능을 필요로합니다.
당신은 당신의 측면에서 "조건 필드"에 접근 할 수 있어야합니다 그리고 당신은 "조건 필드"인 필드 구성 할 수 있어야합니다. 불행히도 C#에서는 상수 표현식을 속성 인수로 지정할 수 있습니다. 유일한 방법은 (내가 알고)은 "조건 필드"를 지정하는 문자열을 사용 이름 :
[Conditional("Initialized", "Awesome text"]
void Method1()
{
//do stuff;
}
문제는 IntelliSense를 문자열 작동하지 않지만 당신의 측면에서 필드의 존재를 확인할 수있다 .
당신은
ImportLocationAdviceInstance를 사용
IAdviceProvider 구현하여 목표 클래스의 모든 필드를 가져올 수 있습니다
: 이제
[PSerializable]
public class ConditionalAttribute : InstanceLevelAspect, IAdviceProvider
{
private string conditionFieldName;
private string awesomeText;
public ILocationBinding ConditionBindingField;
public ConditionalAttribute(string conditionFieldName, string awesomeText)
{
this.conditionFieldName = conditionFieldName;
this.awesomeText = awesomeText;
}
public IEnumerable<AdviceInstance> ProvideAdvices(object targetElement)
{
var targetType = (Type) targetElement;
var bindingFieldInfo = this.GetType().GetField("ConditionBindingField", BindingFlags.Instance | BindingFlags.Public);
foreach (
var field in
targetType.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public |
BindingFlags.NonPublic))
{
if (field.Name == conditionFieldName)
{
if (field.FieldType.IsAssignableFrom(typeof(bool)))
{
yield return new ImportLocationAdviceInstance(bindingFieldInfo, new LocationInfo(field));
yield break;
}
{
Message.Write(MessageLocation.Of(targetType), SeverityType.Error, "ERR002", $"{targetType.Name} contains {field.FieldType.Name} {conditionFieldName}. {conditionFieldName} has to be bool.");
yield break;
}
}
}
Message.Write(MessageLocation.Of(targetType), SeverityType.Error, "ERR001", $"{targetType.Name} doesn't contain {conditionFieldName}");
}
}
, ConditionBindingField
중 하나 "조건 필드"바인딩 포함, 또는 PostSharp가 ERR001 또는 ERR002은 "조건의 경우 방출 필드 "가 존재하지 않거나 bool
이외의 다른 유형으로 선언되었습니다.
[OnMethodInvokeAdvice]
[MethodPointcut("SelectMethods")]
public void OnInvoke(MethodInterceptionArgs args)
{
bool conditionFieldValue = (bool)ConditionBindingField.GetValue(args.Instance);
if (!conditionFieldValue)
{
throw new InvalidOperationException(awesomeText);
}
args.Proceed(); // call original method body
}
PostSharp 인터셉트 OnInvoke 방법에서 코드 SelectMethods
방법에 의해 제공되는 각각의 방법
다음 단계는 인증 코드와 차단 대상 클래스 방법이다. 문제는 "조건 필드"검사를 사용하여 Init
메서드를 가로 채지 않으려는 것입니다. 그렇지 않으면이 메서드를 호출하면 예외가 발생하고 클래스를 초기화 할 수 없습니다. 따라서 요격 할 수없는 방법을 어떻게 든 표시해야합니다.당신은 사용 규칙과 하나가 모든 Init
방법에 같은 이름을 부여 할 수 있습니다 또는 당신은 속성 Init
방법을 표시 할 수 있습니다
private IEnumerable<MethodInfo> SelectMethods(Type type)
{
const BindingFlags bindingFlags = BindingFlags.Instance |
BindingFlags.DeclaredOnly | BindingFlags.Public;
return type.GetMethods(bindingFlags)
.Where(m => !m.GetCustomAttributes(typeof(InitAttribute)).Any());
}
:
[AttributeUsage(AttributeTargets.Method)]
public class InitAttribute : Attribute
{
}
당신은 Init
특성이없는 공공 인스턴스 메소드를 선택 MethodPointcut을 사용할 수 있습니다
조건부 사용법의 예 :
[Conditional("Initialized", "Awesome text")]
class MyClass
{
bool Initialized;
[Init]
void Init()
{
Initialized = true;
}
void Method1()
{
//do stuff;
}
}
편집 : "cond 대신 문자열로 이름을 지정하는 속성에 의해 ition 필드 "
[Conditional("Awesome text")]
class MyClass
{
[ConditionField]
bool Initialized;
[Init]
void Init()
{
Initialized = true;
}
void Method1()
{
//do stuff;
}
}
범프 ........... – Xtro
당신은뿐만 아니라 필드와 (자동) 속성에 계약을 적용 할 수 있습니다. 이것은 PostSharp에서 가능합니다 :'[Required] string f1;','[필수] public string P1 {get; 세트; }'. 필드 또는 속성에 값이 할당되면 유효성 검사가 트리거됩니다. 그것은 당신의 필요를 해결합니까? 그렇지 않은 경우 사용 사례를 자세히 설명해 주시겠습니까? –
유스 케이스를 추가했습니다. – Xtro