When is a custom attribute's constructor run? - c#

When is it run? Does it run for each object to which I apply it, or just once? Can it do anything, or its actions are restricted?

When is the constructor run? Try it out with a sample:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Creating MyClass instance");
MyClass mc = new MyClass();
Console.WriteLine("Setting value in MyClass instance");
mc.Value = 1;
Console.WriteLine("Getting attributes for MyClass type");
object[] attributes = typeof(MyClass).GetCustomAttributes(true);
}
}
[AttributeUsage(AttributeTargets.All)]
public class MyAttribute : Attribute
{
public MyAttribute()
{
Console.WriteLine("Running constructor");
}
}
[MyAttribute]
class MyClass
{
public int Value { get; set; }
}
And what is the output?
Creating MyClass instance
Setting value in MyClass instance
Getting attributes for MyClass type
Running constructor
So, the attribute constructor is run when we start to examine the attribute. Note that the attribute is fetched from the type, not the instance of the type.

The constructor is run every time the GetCustomAttributes is invoked, or whenever some other code invokes the constructor directly (not that there's a good reason to do so, but it's not impossible either).
Note that at least in .NET 4.0, the attribute instances are not cached; a fresh instance is constructed every time GetCustomAttributes is called:
[Test]
class Program
{
public static int SomeValue;
[Test]
public static void Main(string[] args)
{
var method = typeof(Program).GetMethod("Main");
var type = typeof(Program);
SomeValue = 1;
Console.WriteLine(method.GetCustomAttributes(false)
.OfType<TestAttribute>().First().SomeValue);
// prints "1"
SomeValue = 2;
Console.WriteLine(method.GetCustomAttributes(false)
.OfType<TestAttribute>().First().SomeValue);
// prints "2"
SomeValue = 3;
Console.WriteLine(type.GetCustomAttributes(false)
.OfType<TestAttribute>().First().SomeValue);
// prints "3"
SomeValue = 4;
Console.WriteLine(type.GetCustomAttributes(false)
.OfType<TestAttribute>().First().SomeValue);
// prints "4"
Console.ReadLine();
}
}
[AttributeUsage(AttributeTargets.All)]
class TestAttribute : Attribute
{
public int SomeValue { get; private set; }
public TestAttribute()
{
SomeValue = Program.SomeValue;
}
}
It is not the best idea to have attributes behave like this, of course. At the very least, note that GetCustomAttributes is not documented to behave like this; in fact, what happens in the above program is not specified in the documentation.

Set a debugger break-point inside an attribute constructor and write some reflection code that reads those attributes. You'll notice that the attribute objects won't be created until they are returned from the relfection API. Attributes are per class. They are part of the meta data.
Have a look at this:
Program.cs
using System;
using System.Linq;
[My(15)]
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Program started");
var ats =
from a in typeof(Program).GetCustomAttributes(typeof(MyAttribute), true)
let a2 = a as MyAttribute
where a2 != null
select a2;
foreach(var a in ats)
Console.WriteLine(a.Value);
Console.WriteLine("Program ended");
Console.ReadLine();
}
}
MyAttribute.cs
using System;
[AttributeUsage(validOn : AttributeTargets.Class)]
public class MyAttribute : Attribute
{
public MyAttribute(int x)
{
Console.WriteLine("MyAttribute created with {0}.", x);
Value = x;
}
public int Value { get; private set; }
}
Result
Program started
MyAttribute created with 15.
15
Program ended
But don't worry about the performance of attribute constructors. They are the fastest part of reflection :-P

The metadata in the executable or DLL stores:
A metadata token indicating the constructor to call
The arguments
When I get to that section of my CLI implementation, I plan to lazy-call the constructor the first time GetCustomAttributes() is called for the ICustomAttributeProvider. If a particular attribute type is requested, I'll only construct the ones required to return that type.

Related

Value of a CustomAttribute

I'm trying to understand how custom attributes work.
I have the following code (Which is mostly based on this SO answer):
class Test
{
public static void Main()
{
Console.WriteLine("before class constructor");
var test = new TestClass();
Console.WriteLine("after class constructor");
Attribute[] attributes = Attribute.GetCustomAttributes(test.GetType());
}
}
public class TestClassAttribute : Attribute
{
public TestClassAttribute()
{
Second = "hello";
Console.WriteLine("I am here. I'm the attribute constructor!");
}
public String First { get; set; }
public String Second { get; set; }
public override String ToString()
{
return String.Format("MyFirst: {0}; MySecond: {1}", First, Second);
}
}
[TestClass(First = "customized")]
public class TestClass
{
public int Foo { get; set; }
}
I put a breakpoint on Main's last line, and using the debugger I dived into the source code until the TestClassAttribute constructor got called (happens inside the unsafe overload of CustomAttribute.GetCustomAttributes). Once passed the constructor's first line, I have the following content on the Locals window:
Questions:
Why this's value is the value that gets returned from ToString?
MyFirst has no value. On what moment it will [EDIT: i.e., what method in System.CustomAttribute initializes this property]? (Couldn't see it happening with the debugger, I don't know why).
ToString is really designed (read: was designed) as a debugging tool and that is why it shows up as the local value in the Locals window.
It appears that any names parameters to an attribute are assignments after the constructor is run. Loosely this is how I think the compiler interprets that:
TestClassAttribute instance = new TestClassAttribute();
instance.First = "customized";

How is the new keyword used to hide a method?

I have read an article regarding the new keyword. It says it is used to hide methods. This is example they give:
using System;
namespace ConsoleApplication3
{
class SampleA
{
public void Show()
{
Console.WriteLine("Sample A Test Method");
}
}
class SampleB:SampleA
{
public void Show()
{
Console.WriteLine("Sample B Test Method");
}
}
class Program
{
static void Main(string[] args)
{
SampleA a = new SampleA();
SampleB b = new SampleB();
a.Show();
b.Show();
a = new SampleB();
a.Show();
Console.ReadLine();
}
}
}
Output:
Sample A Test Method
Sample B Test Method
Sample A Test Method
So my question isn't the new keyword used to instantiated an object? and its used to allocate memory for new created objects? Then how can method hiding be done using it? And is above example correct?
new is used for 3 different things. You could say there are 3 different keywords with the same name.
It's an operator, used to invoke constructors. Example: new object();
It's a modifier, used to hide an inherited member from a base class member. Example:
class Base {
public void MyMethod() {
//Do stuff
}
}
class Derived : Base {
public new void MyMethod() {
//Do other stuff
}
}
It's a generic type constraint, used to indicate that a generic type parameter has a parameterless constructor. Example:
class MyGenericClass<T> : where T : new() { ... }
Source: new
Isn't the new keyword used to instantiated an object?
Yes it is. Among other things.
then how can method hiding done using it?
The new keyword in the context of method and property definitions has another meaning than the new keyword used to instantiate objects. The new keyword in that context tells that there is a new start of the inheritance tree of that particular method or property. That's all.
Then how can method hiding be done using it? And is above example
correct?
Programming language syntax, grammar and semantics are just an arbitrary set of conventions and specifications. That is, C# can invent one, two or dozen of usages of a given keyword like new.
When new is used during a class member declaration, it means that you're re-using an identifier:
public class A
{
public string Text { get; set; }
}
public class B : A
{
new public int Text { get; set; }
}
As you can check in above code sample, B also implements a Text property, but since derives from A which has also defined a Text property, there's a naming collision.
The so-called new keyword can be used to re-use Text identifier and being able to implement another property Text which may behave absolutely different than the one implemented in the base class. See that Text on B is of type int!
The most important point here is that re-using identifiers isn't the same as using polymorphism, where a class method or property override must match base class' member signature:
public class A
{
public virtual string Text { get; set; }
}
public class B : A
{
public override string Text
{
get { return base.Text; }
set { base.Text = value; }
}
}
Also, re-used identifiers are dangerous:
public class A
{
public string Text { get; set; }
}
public class B : A
{
new public int Text { get; set; }
}
B b = new B();
b.Text = 4;
// Upcast B to A
A a = b;
a.Text = "Bye bye";
Console.WriteLine(a.Text); // Output: Bye bye
Console.WriteLine(b.Text); // Output: 4
See the output of Text. Since re-using identifiers isn't polymorphism, and in above case both are completely different properties, there's an A.Text and B.Text that can be set separately.
To hide an inherited member, declare it in the derived class by using the same member name, and modify it with the new keyword. For example:
public class BaseC
{
public static int x = 55;
public static int y = 22;
}
public class DerivedC : BaseC
{
// Hide field 'x'.
new public static int x = 100;
static void Main()
{
// Display the new value of x:
Console.WriteLine(x);
// Display the hidden value of x:
Console.WriteLine(BaseC.x);
// Display the unhidden member y:
Console.WriteLine(y);
}
}
/*
Output:
100
55
22
*/
You can read more in here

creating custom attribute with logic inside

I have this custom attribute here where it does some logics
[AttributeUsage(AttributeTargets.All)]
public class CustomAttribute : Attribute
{
public CustomAttribute ()
{
bool foo = false;
if (foo)
Console.WriteLine ("TRUE");
}
}
then i want to use it in my component class like this
[Custom]
public class Component
{
public void Test()
{
console.log("test");
}
}
so what i want is every time i created an instance of that component class, it will basically call or execute that code in my attribute to do some logic, but the problem is, it doesn't execute the code inside my custom attribute class. I know I'm doing it wrong, anyone has idea how to do it?
When the class is instantiated, it will not inherently call any code tied to your attribute, or even instantiate it. Attributes are only instantiated when you call them using reflection. If you would want the attributes to be processed when a class is constructed, you would have to call a method in a constructor on your Component class that uses reflection to analyze the attributes on your class.
The ideal approach would be instead to inherit from a base class that has constructor logic:
public class Component : CustomBase
{
public void Test()
{
console.log("test");
}
}
public abstract class CustomBase
{
public CustomBase()
{
bool foo = false;
if (foo)
Console.WriteLine ("TRUE");
}
}
You need to call:
object[] attributes = typeof(MyClass).GetCustomAttributes(true);
somewhere, because this is the code that triggers the attributes constructor to run.
You can make a method in your attribute class, that calls this line, and in your Component, call the attribute method.
As Jason and Cristina said , you need to take account of reflection to code with custom attributes. If you read the code below (from line 18 to 24) you can see some commented out code that list all the CustomAttributes associated with a type.
using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CustomAttributeTest
{
class Program
{
static void Main(string[] args)
{
var customCompo = new Component();
customCompo.Test();
//System.Reflection.MemberInfo info = typeof(Component);
//object[] attributes = info.GetCustomAttributes(true);
//for (int i = 0; i < attributes.Length; i++)
//{
// System.Console.WriteLine(attributes[i]);
//}
Console.ReadLine();
}
}
[CustomAttribute(true)]
public class Component
{
public void Test()
{
System.Console.WriteLine("Component contructed");
var member = typeof(Component);
foreach (object attribute in member.GetCustomAttributes(true))
{
if (attribute is CustomAttribute)
{
//noop
}
}
}
}
[AttributeUsage(AttributeTargets.All)]
public class CustomAttribute : Attribute
{
private bool _value;
//this constructor specifes one unnamed argument to the attribute class
public CustomAttribute(bool value)
{
_value = value;
Console.WriteLine(this.ToString());
}
public override string ToString()
{
string value = "The boolean value stored is : " + _value;
return value;
}
}
}

initialize constructor with new inside class in C#

I'm new to C# programming. I want to know why this is not possible:
// In file1.cs
public class Test {
public int Rt() {
return 10;
}
}
// In file2.cs
public class Test2 {
// initialize constructor here, but return compile-error
Test k = new Test();
static void Main() {
Console.Write(k.Rt()); // error here
}
}
Additional: I am learning C# for unity, so I also want to know if above is not possible then why this is not an error in unity
public class PlayerScript: MonoBehaviour {
public Vector2 speed = new Vector2(25, 25); // Not an error
void Update() {
Debug.Log(speed); // works
}
}
You're trying to access an instance member inside a static method. That's not allowed. You can define k as static to make it work
static Test k = new Test();
I recommend you to take a look to Static Classes and Static Class Members to get more details
The static member is callable on a class even when no instance of the class has been created. The static member is always accessed by the class name, not the instance name. Only one copy of a static member exists, regardless of how many instances of the class are created. Static methods and properties cannot access non-static fields and events in their containing type, and they cannot access an instance variable of any object unless it is explicitly passed in a method parameter.
In addition to the other answers, another option is to make your Test class and Rt method static. Like so:
public class Program
{
public static void Main()
{
Console.Write(Test.Rt());
}
}
public static class Test {
public static int Rt() {
return 10;
}
}
You really don't have many cases to use a static class though they do exist. I would just move Test t = new Test(); inside your Main method.
public class Program
{
public static void Main()
{
Test t = new Test();
Console.Write(t.Rt());
}
}
public class Test {
public int Rt() {
return 10;
}
}
This is because your Main method is static but your Test2 class is not static. The k variable lives in an instance of Test2 but the Main method belongs to the type itself. If something is static, it means you can call it without instantiating a variable of that type:
Test2.Main();
If you attempted to instantiate a Test2 and call Main you'd get an error because it's static.
var test2 = new Test2();
test2.Main(); //ERROR
You can make k static for this to compile:
public class Test2 {
// initialize constructor here, but return compile-error
static Test k = new Test();
static void Main() {
Console.Write(k.Rt()); // error here
}
}
The second example you showed works fine because the Update method is not static, which means that the method lives with an instantiation of PlayerScript, unlike the Main method.

Get custom attribute from SubClass in BaseClass (C# .NET 4.0)

Ok, edited the code for clarification:
Question: How can I access the attribute [MyAttr("...")] in TestClassOne/Two from BaseClass.TheAttribute...?
All classes except TestClassOne/Two will be compiled in to my "core" and delivered as a dev-platform to a customer.
The TestClassOne/Two is developed by the customer, so there can be no knowledge of the TestClassOne/Two in the "core".
Code below is compiled into "core" and delivered to customer as dll.
[TestMethod()]
public void AttrTest()
{
var one = new TestClassOne();
var attrOne = one.MyTestProperty.TheAttribute;
var two = new TestClassTwo();
var attrTwo = two.MyTestProperty.TheAttribute;
}
public class MyAttr : Attribute
{
private string _test;
public MyAttr(string test)
{
this._test = test;
}
}
public class BaseClass
{
public string TheAttribute
{
get {
// Here I would like to get the "[MyAttr("...")]" from the classes in the bottom
return null;
}
}
}
public class SubClass : BaseClass
{
}
Code below is developed by customer (using my dll's)
public class TestClassOne
{
[MyAttr("Attribute one")]
public SubClass MyTestProperty = new SubClass();
}
public class TestClassTwo
{
[MyAttr("Attribute two")]
public SubClass MyTestProperty = new SubClass();
}
You can get directly from type Test:
var result = typeof (Test)
.GetField("MyTest", BindingFlags.Public | BindingFlags.Instance)
.GetCustomAttribute<MyAttr>();
Edit 3:
You can walk the call stack, looking for a relevant attribute in a relevant member in a relevant class. Try this:
public class MyAttr : Attribute
{
private string _test;
public MyAttr(string test)
{
this._test = test;
}
public string getAttr()
{
return _test;
}
}
public class BaseClass
{
private string theString;
public BaseClass()
{
StackTrace callStack = new StackTrace();
for ( int i = 0; i < callStack.FrameCount; i++ )
{
Type t = callStack.GetFrame(i).GetMethod().DeclaringType;
foreach ( MemberInfo m in t.GetMembers().Where(x => typeof(BaseClass).IsAssignableFrom(x.Type)) )
{
foreach ( var z in m.GetCustomAttributes(typeof(MyAttr)) )
{
MyAttr theAttr = z as MyAttr;
if ( z!= null )
{
theString = z.getAttr();
return;
}
}
}
}
}
public string Test
{
get {
return theString;
}
}
}
This requires that your customer always initializes the SubClass member inside the class that declares it. If they start deriving TestClassOne or have it and TestClassTwo derive from a common class that initializes the member, this code will break.
With clever use of reflection, you can expand the above code to cover more use cases, but that's beyond the scope of this question.
Edit 2:
No. I'm sorry, but what you're trying to do isn't possible. There's no "normal" way for an instance of SubClass to know if it's being declared in a member field of some other object, or in an element in an array or in a temporary variable in the stack, or whatever. As such, there's no way for that instance to access the attributes of the member field that's declaring it.
(I suppose you might want to try to access the garbage collector to find out where in memory the this object lives, but that's probably way beyond the scope of this problem, and in any case, not something I know how to do.)
I suspect your problem lies elsewhere entirely. Maybe you need to require your customer to make TestClassOne and TestClassTwo derive from a common abstract class. Maybe they need to derive from BaseClass themselves. Maybe you need to add parameters to the constructor. Maybe you need to provide a different interface altogether. We can't know unless you provide more information on your specific business requirements.
Edit:
To access the attributes declared on the MyTest member, try something along these lines:
public class BaseClass
{
public string Test
{
get {
var attr = typeof(Test).GetMembers().Where(x => x.Type == this.GetType()).First().GetCustomAttributes(true);
return null;
}
}
}
This will search class Test for a member with the same type as this and look for attributes on that member.
(I don't have my Visual Studio here, to check the exact Where syntax, but it should be pretty close to that...)
Original Answer:
Your attribute is declared on the MyTest member of class Test. But, you're doing GetCustomAttributes on class SubClass itself.
Try this:
[MyAttr("apa")]
public class SubClass : BaseClass
{
}
public class Test
{
public SubClass MyTest = new SubClass();
}
Should get you what you want.

Categories