내 사용자 정의 속성이 적용된 멤버를 가져 오려면 어떻게합니까?
C #에서 사용자 지정 특성 을 만들고 있으며 특성이 메서드와 속성에 적용되는지 여부에 따라 다른 작업을 수행하고 싶습니다. 처음에는 new StackTrace().GetFrame(1).GetMethod()
속성 생성자라고 부르는 메서드를 확인하기 위해 사용자 지정 속성 생성자에서 수행하려고 했지만 지금은 그것이 내게 무엇을 제공할지 확신 할 수 없습니다. 속성이 속성에 적용된 경우 어떻게됩니까? 시겠습니까 GetMethod()
반환 MethodBase
하는 속성에 대한 인스턴스를? C #에서 특성이 적용된 멤버를 가져 오는 다른 방법이 있습니까?
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property,
AllowMultiple = true)]
public class MyCustomAttribute : Attribute
업데이트 : 좋아, 잘못된 질문을했을 수도 있습니다. 사용자 지정 특성 클래스 내에서 사용자 지정 특성이 적용된 멤버 (또는 멤버가 포함 된 클래스)를 가져 오려면 어떻게합니까? Aaronaught 는 내 속성이 적용된 클래스 멤버를 찾기 위해 스택을 걸어가는 것을 반대했지만 내 속성의 생성자 내에서이 정보를 어떻게 얻습니까?
스택 프레임과 메서드가 작동하는 방식과 관련하여 많은 혼란이있는 것 같으므로 다음은 간단한 데모입니다.
static void Main(string[] args)
{
MyClass c = new MyClass();
c.Name = "MyTest";
Console.ReadLine();
}
class MyClass
{
private string name;
void TestMethod()
{
StackTrace st = new StackTrace();
StackFrame currentFrame = st.GetFrame(1);
MethodBase method = currentFrame.GetMethod();
Console.WriteLine(method.Name);
}
public string Name
{
get { return name; }
set
{
TestMethod();
name = value;
}
}
}
이 프로그램의 출력은 다음과 같습니다.
set_Name
C #의 속성은 구문 설탕의 한 형태입니다. 이들은 IL에서 getter 및 setter 메서드로 컴파일되며 일부 .NET 언어는 속성으로 인식하지 못할 수도 있습니다. 속성 확인은 전적으로 관례에 의해 수행되며 IL 사양에는 실제로 규칙이 없습니다.
이제 프로그램이 자신의 스택을 조사하기를 원하는 정말 좋은 이유가 있다고 가정 해 봅시다 ( 그렇게하는 실질적인 이유가 거의 없습니다 ). 왜 세상에서 속성과 메서드에 대해 다르게 작동하기를 원합니까?
속성의 전체적인 근거는 속성이 일종의 메타 데이터라는 것입니다. 다른 동작을 원하면 속성에 코딩하십시오 . 속성이 메서드 또는 속성에 적용되는지 여부에 따라 두 가지 다른 의미를 가질 수있는 경우 두 개의 속성 이 있어야 합니다 . 첫 번째 목표를로 설정하고 AttributeTargets.Method
두 번째 목표 를 AttributeTargets.Property
. 단순한.
그러나 다시 한 번, 호출 메서드에서 일부 속성을 선택하기 위해 자신의 스택을 걷는 것은 기껏해야 위험합니다. 어떤면에서 여러분은 프로그램의 디자인을 동결하여 누구든지 확장하거나 리팩토링하는 것을 훨씬 더 어렵게 만듭니다. 이것은 속성이 일반적으로 사용되는 방식이 아닙니다. 더 적절한 예는 유효성 검사 속성과 같은 것입니다.
public class Customer
{
[Required]
public string Name { get; set; }
}
그런 다음 전달되는 실제 엔티티에 대해 아무것도 모르는 유효성 검사기 코드는 다음을 수행 할 수 있습니다.
public void Validate(object o)
{
Type t = o.GetType();
foreach (var prop in
t.GetProperties(BindingFlags.Instance | BindingFlags.Public))
{
if (Attribute.IsDefined(prop, typeof(RequiredAttribute)))
{
object value = prop.GetValue(o, null);
if (value == null)
throw new RequiredFieldException(prop.Name);
}
}
}
즉, 주어진 인스턴스 의 속성을 검사하고 있지만 유형에 대해 알 필요는 없습니다. XML 특성, 데이터 계약 특성, 심지어 특성 특성까지-.NET Framework의 거의 모든 특성이 이러한 방식으로 사용 되어 인스턴스 유형에 대해서는 동적 이지만 프로그램 의 상태 와 관련이없는 일부 기능을 구현 하거나 스택에있는 일. 스택 추적을 만드는 지점에서 실제로 이것을 제어 할 가능성은 거의 없습니다.
So I'm going to recommend again that you don't use the stack-walking approach unless you have an extremely good reason to do so which you haven't told us about yet. Otherwise you are likely to find yourself in a world of hurt.
If you absolutely must (don't say we didn't warn you), then use two attributes, one that can apply to methods and one that can apply to properties. I think you'll find that to be much easier to work with than a single super-attribute.
Attributes provide metadata and don't know anything about the thing (class, member, etc.) they are decorating. On the other hand, the thing being decorated can ask for the attributes it is decorated with.
If you must know the type of the thing being decorated you will need to explicitly pass it to your attribute in its constructor.
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property,
AllowMultiple = true)]
public class MyCustomAttribute : Attribute
{
Type type;
public MyCustomAttribute(Type type)
{
this.type = type;
}
}
custom attributes are activated by some code calling the GetCustomAttributes method on the ICustomAttributeProvider (reflection object) that represents the location where the attribute is applied. So in the case of a property, some code would obtain the PropertyInfo for the property and then call GetCustomAttributes on that.
If you want to build out some validation framework you would need to write the code that inspects types & members for custom attributes. You could for example have an interface that attributes implement to participate in your validation framework. Could be as simple as the following:
public interface ICustomValidationAttribute
{
void Attach(ICustomAttributeProvider foundOn);
}
Your code could look for this inteface on (for example) a Type:
var validators = type.GetCustomAttributes(typeof(ICustomValidationAttribute), true);
foreach (ICustomValidationAttribute validator in validators)
{
validator.Attach(type);
}
(presumably you would walk the whole reflection graph and do this for each ICustomAttributeProvider). For an example of a similar approach in action in the .net FX you can look at WCF's 'behaviors' (IServiceBehavior, IOperationBehavior, etc).
Update: the .net FX does have a sort-of general purpose, but basically undocumented interception framework in the form of ContextBoundObject and ContextAttribute. You can search the web for some examples of using it for AOP.
GetMethod
will always return you the function name. If it is a property, you will get either get_PropertyName
or set_PropertyName
.
A property is basically a type of method, so when you implement a property, the compiler creates two separate functions in the resulting MSIL, a get_ and a a set_ methods. This is why in the stack trace you receive these names.
ReferenceURL : https://stackoverflow.com/questions/2168942/how-do-i-get-the-member-to-which-my-custom-attribute-was-applied
'IT TIP' 카테고리의 다른 글
두 번째 주마다 작업을 실행하도록 cron에 지시하는 방법은 무엇입니까? (0) | 2020.12.30 |
---|---|
파이썬은 튜플 목록을 어떻게 정렬합니까? (0) | 2020.12.30 |
컴퓨터가 절전 모드에서 다시 시작될 때 데스크톱 브라우저가 감지 할 수 있습니까? (0) | 2020.12.30 |
C # 4.0 app.config에서 섹션을 어떻게 사용합니까? (0) | 2020.12.30 |
프로그래밍 방식으로 IIS Express 시작 및 중지 (0) | 2020.12.30 |