Hello Everyone, Is there a way to detect the existence of constraint aspect attributes like [NotNullConstraint] over a field ?

I tried :

var attributes = CustomAttributeData.GetCustomAttributes(field.UnderlyingProperty);

and :

var attributes = PostSharp.Aspects.Aspect.GetCustomAttributes(field.UnderlyingProperty, false);

but in both cases I get only [Field] attribute in the returned collection. BTW, field is obtained by getting entity TypeInfo from Domain.Current.Model.Types.Entities then iterating through the Fields property of it.

asked Sep 14 '10 at 04:03

msameer's gravatar image

msameer
29559

edited Sep 14 '10 at 06:32

Alex%20Yakunin's gravatar image

Alex Yakunin
29714412


2 Answers:

Hello Mohammed Sameer,

I've investigated the case and noticed that in fact, attributes are applied not on Property itself, but on its getter & setter methods, for example:

[Field(Length=100)]
public string Text
{
  [NotNullOrEmptyConstraint, CompilerGenerated]
  get { return base.GetFieldValue<string>("Text"); }
...

As a result, the code in your test project simply can't find the attributes:

property.GetAttribute<NotNullConstraint>();

But the following code will do what you are expecting:

property.GetGetMethod().GetAttribute<NotNullConstraint>();
property.GetSetMethod().GetAttribute<NotNullConstraint>();

Hope that helps.

answered Oct 14 '10 at 10:05

Dmitri%20Maximov's gravatar image

Dmitri Maximov
22111211

Yes indeed. That solved the problem. Thank you very much.

(Oct 17 '10 at 04:40) msameer msameer's gravatar image

Are you trying to get runtime aspect instance, or just an attribute? They're different:

  • Runtime instance is deserialized & assigned to static field by PostSharp. In general case pretty difficult to find it - try .NET Reflector, but remember that static field names may vary in each post-processed .exe.
  • Regular attribute instance is easy to get - you can use any standard way here, or our own AttributeHelper.GetAttribute<TAttribute>(...) extension method.

But, if you're talking precisely about PropertyConstraintAspect descendants, there is almost legal way to get all the constraints of this type applied to any other type. You need Xtensive.Integrity.Aspects.ConstraintRegistry.GetConstraints(Type type) method. It is internal, but you can invoke it via reflection.

Its intended usage is clear from ValidationAwareExtensions.CheckConstraints code:

public static void CheckConstraints(this IValidationAware target)
{
  var constraints = ConstraintRegistry.GetConstraints(target.GetType());
  if (constraints.Length > 0)
    using (var aggregator = new ExceptionAggregator())
      foreach (var constraint in constraints)
        aggregator.Execute(constraint.Check, target);
}

This method will work only if target type was already initialized (i.e. its type initializer was already invoked). Type initialization leads to invocation of OnRuntimeInitialize method of all the aspects applied to it, and that's where they're registered in ConstraintRegistry.

ConstraintRegistry is fully thread-safe.

answered Sep 14 '10 at 06:08

Alex%20Yakunin's gravatar image

Alex Yakunin
29714412

edited Sep 14 '10 at 06:12

Forgot to add: runtime aspect instances must be more attractive, since only these instances are practically usable (i.e. Check method works there).

Aspects provided by reflection might be interested only if you need just to study their fields, but not check the constraints.

(Sep 14 '10 at 06:14) Alex Yakunin Alex%20Yakunin's gravatar image

Hmm - just checked, the way with getting regular .NET attribute won't work. Most of our aspects are't decorated with PersisteMetaData = true, so PostSharp removes them.

We'll fix this, where this is desirable (e.g. in this case).

(Sep 14 '10 at 06:30) Alex Yakunin Alex%20Yakunin's gravatar image

Thank you very much. Looking forward to seeing it soon :) BTW, ConstraintRegistry.GetConstraints(Type type) does not seem to be internal but it did not solve my issue I believe because the type is not yet initialized as you said.

(Sep 14 '10 at 06:52) msameer msameer's gravatar image
1

Ok, I have some good news: since the fix was very easy, I included it into the build we planned to publish today (v4.3.5 build 6015). Quick test with reflector shows it works:

public double Height {
    ...
    [RangeConstraint(Min=1, Max=2.13)] // Yes!
    [CompilerGenerated]
    set         {
      ...
    }
}
(Sep 14 '10 at 14:05) Alex Yakunin Alex%20Yakunin's gravatar image

I accepted my own answer (hopefully, this is correct).

(Sep 17 '10 at 01:20) Alex Yakunin Alex%20Yakunin's gravatar image

It did not work for me with neither using GetAttribute or ConstraintRegistry.

(Sep 23 '10 at 03:43) msameer msameer's gravatar image

I rejected the acceptance.

It did not work

What exactly had happened in case with ConstraintRegistry? You can send us the code for analysis, or publish it here.

Concerning GetAttribute - it simply can't fail, above code was copied-n-pasted by me from RedGate Reflector (i just shortened it a bit to fit it nicer into the comment), that analyses metadata relying on .NET reflection. So GetAttribute may fail only because of wrong usage here.

Try to open the assembly with such attributes with Reflector - you'll see them there.

(Sep 23 '10 at 16:12) Alex Yakunin Alex%20Yakunin's gravatar image

P.S. There is a newer DO4 build now, although it doesn't change anything related to this issue.

(Sep 23 '10 at 16:12) Alex Yakunin Alex%20Yakunin's gravatar image

The steps to reproduce the issue are: 1) Make a new DataObjects Console app. 2) Add [NotNullOrEmptyConstraint] to MyEntity.Text. 3) Add static class with a static method having code: foreach (var type in domain.Model.Types) foreach (var field in type.Fields) { var a1 = field.UnderlyingProperty.GetAttribute<notnulloremptyconstraint>(); if (a1 != null) //always null Console.WriteLine(field.Name); } 4) Call it in Main after domain.Build and remove all sample code below it.

(Oct 11 '10 at 07:58) msameer msameer's gravatar image

How can I send the sample project to you ?

(Oct 11 '10 at 07:59) msameer msameer's gravatar image

You can send it to support@x-tensive.com

(Oct 11 '10 at 08:07) Dmitri Maximov Dmitri%20Maximov's gravatar image

I have sent it yesterday.

(Oct 12 '10 at 03:40) msameer msameer's gravatar image

Hello guys, any updates ? Did you receive my sample project? Is there something wrong I am doing?

(Oct 14 '10 at 06:21) msameer msameer's gravatar image

Yes, we've got the project, but were pretty busy with other stuff yet. I'm going to study it today.

(Oct 14 '10 at 09:26) Alex Yakunin Alex%20Yakunin's gravatar image
Your answer
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!
toggle preview

Subscription:

Once you sign in you will be able to subscribe for any updates here

Tags:

×573
×7
×2

Asked: Sep 14 '10 at 04:03

Seen: 3,677 times

Last updated: Oct 17 '10 at 04:40

powered by OSQA