I want to validate condition on class definition in the build process and show build error in case that something is not validated.
In the build process attribute instance is created for each class that defined by this attribute.
I want to check something like for example that the class does not have more than 4 properties(just for example, this is not my intention). How can I get the type from the attribute constructor for each class?
(Without passing it as parameter).
Example:
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class ValidatePropertiesAttribute:ValidationAttribute
{
public ValidatePropertiesAttribute()
{
if(Validate()==false)
{
throw new Exception("It's not valid!! add more properties to the type 'x'.");
}
}
public bool Validate()
{
//check if there are at least 4 properties in class "X"
//Q: How can I get class "X"?
}
}
[ValidateProperties()]
public class ExampleClass
{
public string OnOneProperty { get; set; }
}
Is it possbile?
If not, is there any other way to do it?
(add validation to the build process and show errors in case that something was not validated)
This solution may work
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class ValidatePropertiesAttribute:ValidationAttribute
{
private Type TargetClass;
public ValidatePropertiesAttribute(Type targetClass)
{
TargetClass = targetClass;
if(Validate() == false)
{
throw new Exception("It's not valid!! add more properties to the type 'x'.");
}
}
public bool Validate()
{
//Use Target Class,
//if you need extract properties use TargetClass.GetProperties()...
//if you need create instance use Activator..
}
}
Use this attribute as follows
[ValidateProperties(typeof(ExampleClass))]
public class ExampleClass
{
public string OnOneProperty { get; set; }
}
Related
Is there a way to get custom attributes which are added along the flow? I'm adding custom attributes to different methods in different classes that are called depending on the flow. I've tried MethodBase.GetCurrentMethod() but this (as it says) only the current invoked method. Using new StackFrame(n) also doesn't work since "n" can frequently change. Googled my problem but didn't find any hints.
public class CustomAttribute1 : Attribute
{
public bool Property { get; }
public CustomAttribute1(bool property) => Property = property;
}
public class CustomAttribute2 : Attribute
{
public string Property { get; }
public CustomAttribute2(string property) => Property = property;
}
public class GeneralService
{
protected void Resolve()
{
// Here I want to access custom attributes combined
}
}
public class SpecifiedService : GeneralService
{
[CustomAttribute1(true)]
public void SendRequest()
{
Resolve();
}
}
public class Worker
{
[CustomAttribute2("init")]
public void Init()
{
var service = new SpecifiedService();
service.SendRequest();
}
}
We have a custom ConfigurationManager library that serializes/deserializes a config.json file into an ExpandoObject.
Would it be possible to create a custom attribute that overrides the Getter/Setter of these properties to abstract this ExpandoObject?
Ideally I would be able to use the Attribute like this:
[System.AttributeUsage(System.AttributeTargets.Property)]
class Configureable : System.Attribute
{
public string Default { get; set; }
public bool IsEncrypted { get; set; }
}
class Test
{
[Configureable(Default = "0",IsEncrypted = false)]
public string MyValue { get; set; }
}
When I set the value of the decorated property I want to auto-magically update the value of the ExpandoObject, which would then in turn force an update be written to my config.json file.
When I access the value of the decorated property I want the getter to actually return the value of the underlying ExpandoObject. I can do this by manually having the developer modify the getter/setter. I was wondering if I could also do this with code inside of the attribute.
Thank you!
I found http://doc.postsharp.net/location-interception
That seems to do exactly what I want.
[System.AttributeUsage(System.AttributeTargets.Property)]
[Serializable]
class Configureable : LocationInterceptionAspect
{
public string Default { get; set; }
public bool IsEncrypted { get; set; }
public override void OnGetValue(LocationInterceptionArgs args)
{
base.OnGetValue(args);
if (args.Value == null)
{
}
}
public override void OnSetValue(LocationInterceptionArgs args)
{
//base.OnSetValue(args);
}
}
class Test
{
[Configureable(Default = "0",IsEncrypted = false)]
public string MyValue { get; set; }
}
ExpandoObject is a dictionary with object syntax. It is useful only in simple scenarios. If you need complex logic, use DynamicObject intead. Override its TryGetMember and TrySetMember methods to replicate functionality of ExpandoObject, then customize logic of these methods in the way you want.
It's not clear what your requirements are though. If you have a class which holds properties, what is the point of having dynamic objects?
Attribute constructors are called after calling GetCustomAttributes() on a type that is decorated with attributes. Is it possible to determine the calling type from within the constructor. I would like to do something similar to the following and have it not throw.
class Program
{
static void Main(string[] args)
{
var myAttributedClassType = typeof(MyAttributedClass);
var customAttributes = myAttributedClassType.GetCustomAttributes(false)
.OfType<MyAttribute>();
if (customAttributes.Any(x => x.CallingType != myAttributedClassType))
{
throw new Exception("MyAttribute.CallingType was incorrect.");
}
}
}
[AttributeUsage(AttributeTargets.Class)]
class MyAttribute : Attribute
{
public Type CallingType { get; set; }
public MyAttribute()
{
// magic to set CallingType goes here
}
}
[MyAttribute]
class MyAttributedClass { }
UPDATE:
I know that this can be done easily through named parameters in the constructor
[MyAttribute(CallingType = typeof(MyAttributedClass)
or a required parameter
public MyAttributed(Type callingType)
{
CallingType = callingType; // this doesn't qualify as magic ;)
}
but was hoping there was a way to avoid it since the type object itself (the value I want) is the caller of GetCustomAttributes
Your magic, not really magic though:
[AttributeUsage(AttributeTargets.Class)]
class MyAttribute : Attribute
{
public Type CallingType { get; set; }
public MyAttribute(Type type)
{
// heres your magic
this.CallingType = type;
}
}
Usage:
[MyAttribute(typeof(MyClass))]
Say I have code out there like this:
public class Base // I cannot change this class
{
public string Something { get; private set; }
public string Otherthing { get; set; }
public static Base StaticPreSet
{
get { return new Base { Something = "Some", Otherthing = "Other"}; }
}
public static Base StaticPreSet2
{
get { return new Base { Something = "Some 2", Otherthing = "Other 2"}; }
}
}
public class SubClass : Base // I can change this class all I want.
{
public string MoreData { get; set; }
// How can I wrap the PreSets here so that they return SubClass objects?
// Something like this:
public static SubClass MyWrappedPreset
{
get
{
// Code here to call the base preset and then use it as the
// base of my SubClass instance.
}
}
}
What makes this complicated is the Something property. It has a private setter. So I can't set it in the subclass. The only way it can be set is is via the preset properties.
Is there a way to wrap the StaticPreSet property in my SubClass so that it will return an object of type SubClass?
// I cannot change this base class.
Given that you can't change the base class, there is no way to cause it to change behavior (ie: return a different class at runtime).
If you could influence the design of the base class static methods, you could redesign it in a way to be flexible enough to provide this functionality. However, without changing it, this won't work.
Edit in response to edit:
You could create a new static method that does what you are showing, like so:
public static SubClass MyWrappedPreset
{
get
{
// Code here to call the base preset and then use it as the
// base of my SubClass instance.
Base baseInstance = Base.StaticPreSet;
SubClass sc = new SubClass(baseInstance); // Create a new instance from your base class
return sc;
}
}
However, this provides a completely new, unrelated property - you'd have to access it via SubClass.MyWrappedPreset, not the Base class.
Static fields in a class "have nothing to do with it".
Basically, except access to private static fields, id doesn't matter in which class you put them - they behave the same.
If you inherit a class, and you declare another static field with the same name of a static field on the base class, you will simply 'hide' it. Example for you:
using System;
public class Base // I cannot change this class
{
public string Something { get; set; }
public string Otherthing { get; set; }
public static Base StaticPreSet
{
get { return new Base { Something = "Some", Otherthing = "Other"}; }
}
public static Base StaticPreSet2
{
get { return new Base { Something = "Some 2", Otherthing = "Other 2"}; }
}
}
public class SubClass : Base // I can change this class all I want.
{
public string MoreData { get; set; }
public static SubClass StaticPreSet2
{
get { return new SubClass { Something = "inherited", Otherthing=""}; }
}
}
public class Test
{
public static void Main()
{
Console.WriteLine(SubClass.StaticPreSet2.Something);
}
}
Will write "inherited".
What's the first line of the following code called?
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public virtual IController Controller
{
get { return controller; }
set { controller = value; }
}
It's called an attribute. Attributes are used to describe properties, methods, etc. They serve to provide metadata, among other things.
In this case, the DesignerSerializationVisibility.Hidden attribute means that the Controller property isn't visible to the design-time serializer.
Positional parameters are parameters of the constructor of the attribute. They are mandatory and a value must be passed every time the attribute is placed on any program entity. On the other hand Named parameters are actually optional and are not parameters of the attribute's constructor.
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false,
Inherited = false)]
public class HelpAttribute : Attribute
{
public HelpAttribute(String Description_in)
{
this.description = Description_in;
this.verion = "No Version is defined for this class";
}
protected String description;
public String Description
{
get
{
return this.description;
}
}
protected String version;
public String Version
{
get
{
return this.version;
}
//if we ever want our attribute user to set this property,
//we must specify set method for it
set
{
this.verion = value;
}
}
}
[Help("This is Class1")]
public class Class1
{
}
[Help("This is Class2", Version = "1.0")]
public class Class2
{
}
[Help("This is Class3", Version = "2.0",
Description = "This is do-nothing class")]
public class Class3
{
}
more...