Thread: Attribute Refuses Cast

  1. #1
    Registered User
    Join Date
    Mar 2006
    Posts
    12

    Question Attribute Refuses Cast

    Edited to rephrase question:

    The following code is driving me nuts! I am trying to read the IDEiconAttribute from each class (e.g. ConsoleInput ) in a library. But, I cannot access the attribute (object) I retrieve as my IDEiconAttribute , so I can't call the IDEiconAttribute.Icon property. It refuses to be cast to IDEiconAttribute, even though when I print out the type, the type is IDEClassLibraryNS.IDEiconAttribute. In fact, I get the bizzare message "cannot cast IDEClassLibraryNS.IDEiconAttribute to IDEClassLibraryNS.IDEiconAttribute".

    Why does this work (in my case)?

    object[] attributes = typeof(Negate).GetCustomAttributes (true);

    //Negate is one of the class in the lib

    but this doesn't?

    object[] attributes = type.GetCustomAttributes (true);

    //type is one of the assembly.GetTypes()

    I need to iterate though all the class in the library (as below).

    When I say "doesn't work", I mean the cast following the GetCustomAttributes does or doesn't work.

    ================================================== =====

    Code:
    Assembly assembly = Assembly.LoadFile (@"E:\IDEClassLibrary.dll");
    
    foreach (Type type in assembly.GetTypes())
    
       {
    
       //object[] attributes = underType.GetCustomAttributes (true);
    
       //object[] attributes = typeof(Negate).GetCustomAttributes (true);
    
       //object[] attributes = type.GetCustomAttributes (true);
    
       }
    Jess

    C# Online.NET

    http://wiki.csharp-online.net/

  2. #2
    Anti-Poster
    Join Date
    Feb 2002
    Posts
    1,401
    I don't have any of the problems you are. The following code seems to work fine for locating the Serializable attribute on any type in the assembly. I don't see why it couldn't be modified to search for your attribute.
    Code:
    foreach (Type type in assembly.GetTypes())
    {
    	object[] attributes = type.GetCustomAttributes (true);
    
    	foreach (object obj in attributes)
    	{
    		SerializableAttribute serialAttribute = obj as SerializableAttribute;
    		if (serialAttribute != null)
    		{
    			//work with the attribute if desired
    			Console.WriteLine("{0} has the Serializable attribute", type);
    		}
    	}
    }
    I suspect your error message is coming from an attempt to cast a Type to an actual instance of the class. Of course, that's illegal.
    Quote Originally Posted by Hyle
    Why does this work (in my case)?

    object[] attributes = typeof(Negate).GetCustomAttributes (true);
    I'm surprised you think that works. That line of code gets the attributes from the type Negate, just as it says. However, since you're explicitly stating the class, you're not using reflection, so this assembly must have a reference to the library.
    Last edited by pianorain; 03-20-2006 at 10:11 AM.
    If I did your homework for you, then you might pass your class without learning how to write a program like this. Then you might graduate and get your degree without learning how to write a program like this. You might become a professional programmer without knowing how to write a program like this. Someday you might work on a project with me without knowing how to write a program like this. Then I would have to do you serious bodily harm. - Jack Klein

  3. #3
    Registered User
    Join Date
    Mar 2006
    Posts
    12
    Yeah, I don't know what the problem is: I used your code, changing to my attribute (Serializable is not a normal attribute anyway), and it fails with "IDEiconAttribute attribute = null".

    Code:
    Assembly assembly   = Assembly.LoadFile (@"C:\IDEClassLibrary\IDEClassLibrary\bin
    \Debug\IDEClassLibrary.dll");
    	Console.WriteLine ("Assembly name: {0}\n", assembly);
    
    foreach (Type type in assembly.GetTypes())
    	{
    	object[] attributes = type.GetCustomAttributes (true);
    
    	foreach (object obj in attributes)
    		{
    		IDEiconAttribute serialAttribute = obj as IDEiconAttribute;
    		if (serialAttribute != null)
    			{
    			//work with the attribute if desired
    			Console.WriteLine ("{0} has the IDEiconAttribute attribute", type);
    			}
    		else Console.WriteLine ("IDEiconAttribute attribute = null");
    		}
    	}
    I only said the following works, because it does find my attribute:
    Code:
    object[] attributes = typeof(Negate).GetCustomAttributes (true);
    Thx!

    Jess

    C# Online.NET

    http://wiki.csharp-online.net/

  4. #4
    Anti-Poster
    Join Date
    Feb 2002
    Posts
    1,401
    Quote Originally Posted by Hyle
    (Serializable is not a normal attribute anyway)
    Really? What makes it not a 'normal' attribute?

    I can't help much more because it appears the problem is outside the code that you've given. Here is a complete example of a user-created attribute and finding that attribute using reflection.

    In a class library project Test2005Attribute:
    Code:
    using System;
    
    namespace Test2005Attribute
    {
    	// The AuthorAttribute class is a user-defined attribute class.
    	// It can be applied to classes and struct declarations only.
    	// It takes one unnamed string argument (the author's name).
    	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
    	public class AuthorAttribute : Attribute
    	{
    		private string m_name;
    
    		// This constructor specifies the unnamed argument to the attribute class.
    		public AuthorAttribute(string name)
    		{
    			m_name = name;
    		}
    
    		// This property is readonly (it has no set accessor)
    		// so it cannot be used as a named argument to this attribute.
    		public string Name
    		{
    			get
    			{
    				return m_name;
    			}
    		}
    
    		public override string ToString()
    		{
    			return "Author: " + Name;
    		}
    	}
    }
    In a class library project Test2005Library:
    Code:
    using System;
    using System.Collections;
    using Test2005Attribute;
    
    //Make sure to reference Test2005Attribute.
    namespace Test2005Library
    {
    	//The Author attribute is attached to this class
    	[Author("Joe Bob")]
    	public class BaseTemplate<T>
    		where T : IEnumerable
    	{
    
    	}
    
    	public class A
    	{
    
    	}
    
    	//The Author attribute is attached to this class
    	[Author("Joe Bill")]
    	public class B
    	{
    
    	}
    }
    In a console app project Test2005:
    Code:
    using System;
    using System.Collections;
    using System.Text;
    using System.IO;
    using System.Diagnostics;
    using System.Reflection;
    using Test2005Attribute;
    
    //Make sure to reference Test2005Attribute.
    //Make sure NOT to reference Test2005Library.
    namespace Test2005
    {
    	class Program
    	{
    		static void Main(string[] args)
    		{
    			string path = ""; //put the full path to Test2005Library.dll here
    			Assembly assembly = Assembly.LoadFile(path);
    
    			foreach (Type type in assembly.GetTypes())
    			{
    				object[] attributes = type.GetCustomAttributes (true);
    
    				foreach (object obj in attributes)
    				{
    					AuthorAttribute authorAttribute = obj as AuthorAttribute;
    					if (authorAttribute != null)
    					{
    						Console.WriteLine("{0} has the Author attribute: {1}",
    							type, authorAttribute);
    					}
    					//NOTE: no else statement.  Why?
    					//  Because you're looping through all custom attributes
    					//  on this type.
    				}
    			}
    			Console.WriteLine("Finished");
    			Console.ReadLine();
    		}
    	}
    }
    If I did your homework for you, then you might pass your class without learning how to write a program like this. Then you might graduate and get your degree without learning how to write a program like this. You might become a professional programmer without knowing how to write a program like this. Someday you might work on a project with me without knowing how to write a program like this. Then I would have to do you serious bodily harm. - Jack Klein

  5. #5
    Registered User
    Join Date
    Mar 2006
    Posts
    12

    Smile

    Thanks a lot for your efforts. I'll check out your example.

    Serializable shows up in the assembly as an interface in a declaration, not as an attribute (for example, when you view in ildasm). So, .NET dummies it up somehow to let you retrieve it as an attribute. There are other such anomolies.

    I was able to fix my code from your example--it was a namespace problem. I had my attribute and the library classes in the same namespace. why that wouldn't work, I don't know.

    Thanks a lot for your trouble!

    Jess

    C# Online.NET

    http://wiki.csharp-online.net/
    Last edited by Hyle; 03-21-2006 at 10:50 AM.

  6. #6
    Anti-Poster
    Join Date
    Feb 2002
    Posts
    1,401
    Quote Originally Posted by Hyle
    Serializable shows up in the assembly as an interface in a declaration, not as an attribute (for example, when you view in ildasm). So, .NET dummies it up somehow to let you retrieve it as an attribute. There are other such anomolies.
    Eh, not really. There is the SerializableAttribute attribute and ISerializable interface. Both are independent of each other; classes can implement either one, neither, or both (although it's pretty useless to implement ISerializable and not mark the class with the Serializable attribute). Consider the following example:
    Code:
    using System;
    using System.Collections;
    using System.Runtime.Serialization;
    
    namespace Test2005Library
    {
    	//The Serializable attribute is attached to this class
    	[Author("Joe Bob")]
    	public class BaseTemplate<T>
    		where T : IEnumerable
    	{
    
    	}
    
    	//Implements ISerializable
    	public class A : ISerializable
    	{
    		#region ISerializable Members
    
    		public void GetObjectData(SerializationInfo info, StreamingContext context)
    		{
    			throw new Exception("The method or operation is not implemented.");
    		}
    
    		#endregion
    	}
    
    	//The Serializable attribute is attached to this class
    	//Implements ISerializable
    	[Serializable]
    	public class B : ISerializable
    	{
    		#region ISerializable Members
    
    		public void GetObjectData(SerializationInfo info, StreamingContext context)
    		{
    			throw new Exception("The method or operation is not implemented.");
    		}
    
    		#endregion
    	}
    }
    Code:
    using System;
    using System.Collections;
    using System.Text;
    using System.IO;
    using System.Diagnostics;
    using System.Reflection;
    using System.Runtime.Serialization;
    
    //Make sure to reference Test2005Attribute.
    //Make sure NOT to reference Test2005Library.
    namespace Test2005
    {
    	class Program
    	{
    		static void Main(string[] args)
    		{
    			string path = ""; //put the full path to Test2005Library.dll here
    			Assembly assembly = Assembly.LoadFile(path);
    
    			foreach (Type type in assembly.GetTypes())
    			{
    				object[] attributes = type.GetCustomAttributes (true);
    
    				foreach (object obj in attributes)
    				{
    					SerializableAttribute serialAttribute = 
    						obj as SerializableAttribute;
    					if (serialAttribute != null)
    					{
    						Console.WriteLine("{0} has the Serializable attribute",
    							type);
    					}
    				}
    
    				object[] interfaces = type.GetInterfaces();
    
    				foreach (Type obj in interfaces)
    				{
    					ISerializable serializableObj = obj as ISerializable;
    					if (serializableObj != null)
    					{
    						Console.WriteLine("{0} implements ISerializable",
    							type);
    					}
    				}
    			}
    			Console.WriteLine("Finished");
    			Console.ReadLine();
    		}
    	}
    }
    Output:
    Code:
    Test2005Library.BaseTemplate`1[T] has the Serializable attribute
    Test2005Library.A implements ISerializable
    Test2005Library.B has the Serializable attribute
    Test2005Library.B implements ISerializable
    Finished
    If I did your homework for you, then you might pass your class without learning how to write a program like this. Then you might graduate and get your degree without learning how to write a program like this. You might become a professional programmer without knowing how to write a program like this. Someday you might work on a project with me without knowing how to write a program like this. Then I would have to do you serious bodily harm. - Jack Klein

  7. #7
    Registered User
    Join Date
    Mar 2006
    Posts
    12
    Well, if you examine the class files, you won't find a Serializable attribute as you would find a custom attribute.

    (I edited my earlier post to reflect my success with your example!)

    How about writing an article for us on Custom Attributes?

    Jess

    C# Online.NET

    http://wiki.csharp-online.net/

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Including The Right DLLs
    By bumfluff in forum Game Programming
    Replies: 8
    Last Post: 12-28-2006, 03:32 AM
  2. Replies: 28
    Last Post: 07-16-2006, 11:35 PM
  3. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 06:39 AM
  4. errors in class(urgent )
    By ayesha in forum C++ Programming
    Replies: 1
    Last Post: 11-10-2001, 10:14 PM
  5. errors in class(urgent)
    By ayesha in forum C++ Programming
    Replies: 2
    Last Post: 11-10-2001, 06:51 PM