Type.GetCustomerAttributes(...) Not Working as expected

P

Paul Hadfield

Hi,

I'm running into one problem with trying to call "Type.GetCustomAttributes(...)" on my reflected code. Basically - I can't trap my own custom attribute - I can only catch / identify system "Custom Attributes" by type. The output below identifies that I can catch the "DefaultMemberAttribute", but I can not catch my own "DirectoryVersionAttribute". Cany anyone throw any light on this as it is driving mad

Thanks in Advance,

- Paul.

------------------------------------------------
System.Reflection.DefaultMemberAttribute
System.Reflection.DefaultMemberAttribute
True
System.AttributeUsageAttribute
System.AttributeUsageAttribute
False
System.AttributeUsageAttribute
System.AttributeUsageAttribute
False
MyNameSpace.DirectoryVersionAttribute
MyNameSpace.DirectoryVersionAttribute
False
Press any key to continue . . .
------------------------------------------------

using System;
namespace MyNameSpace
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
public class DirectoryVersionAttribute : System.Attribute
{
private string version = null;
public DirectoryVersionAttribute(string version)
{
this.version = version;
}
public string Version { get { return this.version; } }
}
}

using MyNameSpace;
namespace AnotherNameSpace
{
[DirectoryVersion("1.00")]
public class DirectoryBuilder_v1_00 : IDirectoryBuilder
{
...
}

private void GetBuilderFile(string fileName)
{
Assembly assembly = Assembly.LoadFrom(fileName);
foreach (Type type in assembly.GetTypes())
{
object[] test = type.GetCustomAttributes(typeof(MyNameSpace.DirectoryVersionAttribute), false);
if (test.Length > 0)
{
Console.WriteLine("Wishful Thinking!"); // <<-- Never gets called!
}
test = type.GetCustomAttributes(typeof(Attribute), false);
if (test.Length > 0)
{
Console.WriteLine(((Attribute)test[0]).TypeId);
Console.WriteLine(((Attribute)test[0]).ToString());
Console.WriteLine(((Attribute)test[0]) is System.Reflection.DefaultMemberAttribute);
Console.WriteLine(((Attribute)test[0]) is MyNameSpace.DirectoryVersionAttribute);
}
}
}
 
G

Guest

Paul,

I'm not sure on this as I've only messed with reflection a little but
wouldn't one get the class with the attribute on it first then get the custom
attributes for it? I know this is what I did for custom attributes I put on
some properties one time. Hope this helps.
 
P

Paul Hadfield

Hi Thom,

Whilst this is a code snippet, I have run the full code through the debugger
and the snippet illustrates the area that has the issue. The statement
"foreach (Type type in assembly.GetTypes())" gets a list of the classes that
are defined in that assembly. The output from "test =
type.GetCustomAttributes(typeof(Attribute), false);" shows that the custom
attribute can be retrieved from the class, I'm just not sure why the
GetCustomAttribute using the proper type doesn't return anything.

BTW:

"test = type.GetCustomAttributes(typeof(DefaultMemberAttribute), false);"

returns one element in the array, which is the attribute that has been
defined - it's just why doesn't it work with my custom attributes - what am
I doing wrong / differently?

- Paul.

tbain said:
Paul,

I'm not sure on this as I've only messed with reflection a little but
wouldn't one get the class with the attribute on it first then get the
custom
attributes for it? I know this is what I did for custom attributes I put
on
some properties one time. Hope this helps.
--
Thom


Paul Hadfield said:
Hi,

I'm running into one problem with trying to call
"Type.GetCustomAttributes(...)" on my reflected code. Basically - I
can't trap my own custom attribute - I can only catch / identify system
"Custom Attributes" by type. The output below identifies that I can
catch the "DefaultMemberAttribute", but I can not catch my own
"DirectoryVersionAttribute". Cany anyone throw any light on this as it
is driving mad

Thanks in Advance,

- Paul.

------------------------------------------------
System.Reflection.DefaultMemberAttribute
System.Reflection.DefaultMemberAttribute
True
System.AttributeUsageAttribute
System.AttributeUsageAttribute
False
System.AttributeUsageAttribute
System.AttributeUsageAttribute
False
MyNameSpace.DirectoryVersionAttribute
MyNameSpace.DirectoryVersionAttribute
False
Press any key to continue . . .
------------------------------------------------

using System;
namespace MyNameSpace
{
[AttributeUsage(AttributeTargets.Class, Inherited = false,
AllowMultiple = false)]
public class DirectoryVersionAttribute : System.Attribute
{
private string version = null;
public DirectoryVersionAttribute(string version)
{
this.version = version;
}
public string Version { get { return this.version; } }
}
}

using MyNameSpace;
namespace AnotherNameSpace
{
[DirectoryVersion("1.00")]
public class DirectoryBuilder_v1_00 : IDirectoryBuilder
{
...
}

private void GetBuilderFile(string fileName)
{
Assembly assembly = Assembly.LoadFrom(fileName);
foreach (Type type in assembly.GetTypes())
{
object[] test =
type.GetCustomAttributes(typeof(MyNameSpace.DirectoryVersionAttribute),
false);
if (test.Length > 0)
{
Console.WriteLine("Wishful Thinking!"); // <<-- Never gets
called!
}
test = type.GetCustomAttributes(typeof(Attribute), false);
if (test.Length > 0)
{
Console.WriteLine(((Attribute)test[0]).TypeId);
Console.WriteLine(((Attribute)test[0]).ToString());
Console.WriteLine(((Attribute)test[0]) is
System.Reflection.DefaultMemberAttribute);
Console.WriteLine(((Attribute)test[0]) is
MyNameSpace.DirectoryVersionAttribute);
}
}
}
 
J

Jesse Houwing

* tbain wrote, On 25-5-2007 13:27:
Paul,

I'm not sure on this as I've only messed with reflection a little but
wouldn't one get the class with the attribute on it first then get the custom
attributes for it? I know this is what I did for custom attributes I put on
some properties one time. Hope this helps.

In which Assembly is DirectoryVersion defined. Is it loaded in your test
app?

You might want to load it with Assembly.LoadFrom is this isn't so and
try again.

Jesse
 
P

Paul Hadfield

As shown in original code, I'm using Assembly.LoadFrom() as that's the
reflection bit.

The custom attribute DirectoryVersion is defined in the same assembly as the
code checking for the custom attributes. However in my testing I've moved
the code checking for the customer attribute into another project too -
there was no change in behaviour. The class that has custom attribute
assigned is in a separate assembly (which has a reference to the assembly to
get the definition).

I'm willing to investigate any possibility right now as the difference must
be in my code, but I can't for the life of me see it, and I believe that
I've tried most assembly combinations. I've also tried typeof(...) and
Type.GetType(...)

- Paul.
 
P

Paul Hadfield

Not sure if this might help diagnose the problem, but the code snippet below throws the exception

----------------------------------------------
Unable to cast object of type 'MyNameSpace.DirectoryVersionAttribute' to type 'MyNameSpace.DirectoryVersionAttribute'.
----------------------------------------------

Would cause two apparently similar object types throw an exception on casting.

----------------------------------------------
foreach (Type type in assembly.GetTypes())
{
object[] attributes = type.GetCustomAttributes(false);
foreach (object attribute in attributes)
{
if (attribute.GetType().Name == "DirectoryVersionAttribute")
{
Console.WriteLine("Directory Version: {0}", ((DirectoryVersionAttribute)attribute).Version); // <- Throws Exception here
}
}
}
Hi,

I'm running into one problem with trying to call "Type.GetCustomAttributes(...)" on my reflected code. Basically - I can't trap my own custom attribute - I can only catch / identify system "Custom Attributes" by type. The output below identifies that I can catch the "DefaultMemberAttribute", but I can not catch my own "DirectoryVersionAttribute". Cany anyone throw any light on this as it is driving mad

Thanks in Advance,

- Paul.

------------------------------------------------
System.Reflection.DefaultMemberAttribute
System.Reflection.DefaultMemberAttribute
True
System.AttributeUsageAttribute
System.AttributeUsageAttribute
False
System.AttributeUsageAttribute
System.AttributeUsageAttribute
False
MyNameSpace.DirectoryVersionAttribute
MyNameSpace.DirectoryVersionAttribute
False
Press any key to continue . . .
------------------------------------------------

using System;
namespace MyNameSpace
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
public class DirectoryVersionAttribute : System.Attribute
{
private string version = null;
public DirectoryVersionAttribute(string version)
{
this.version = version;
}
public string Version { get { return this.version; } }
}
}

using MyNameSpace;
namespace AnotherNameSpace
{
[DirectoryVersion("1.00")]
public class DirectoryBuilder_v1_00 : IDirectoryBuilder
{
...
}

private void GetBuilderFile(string fileName)
{
Assembly assembly = Assembly.LoadFrom(fileName);
foreach (Type type in assembly.GetTypes())
{
object[] test = type.GetCustomAttributes(typeof(MyNameSpace.DirectoryVersionAttribute), false);
if (test.Length > 0)
{
Console.WriteLine("Wishful Thinking!"); // <<-- Never gets called!
}
test = type.GetCustomAttributes(typeof(Attribute), false);
if (test.Length > 0)
{
Console.WriteLine(((Attribute)test[0]).TypeId);
Console.WriteLine(((Attribute)test[0]).ToString());
Console.WriteLine(((Attribute)test[0]) is System.Reflection.DefaultMemberAttribute);
Console.WriteLine(((Attribute)test[0]) is MyNameSpace.DirectoryVersionAttribute);
}
}
}
 
P

Paul Hadfield

I've found the cause, but not sure on what is needed for a clean solution! In my solution I have multiple projects, each compiling into their own DLL's. The console application test harness code, which checks for the occurance of the Custom Attribute is in one class has a reference to the project that contains the attribute (these end up in one directory). The code that uses the custom attribute resides in another project, also with a reference to the project that contains the attribute (these end up in another directory). So the DLL containing the attribute definition is local to each directory - hence what I believe to be the clash.

So this does not work (note, DirectoryVersionAttribute.dll is the same dll, just in two places)

\Dir1\
Test.Exe
DirectoryVersionAttribute.dll
\Dir2\
DirectoryLoader.dll
DirectoryVersionAttribute.dll

However the following (same exe / dll's, just copied) works fine

\Dir3\
Test.Exe
DirectoryLoader.dll
DirectoryVersionAttribute.dll

What is the best solution to this problem, should I start looking into using the GAC ?
Not sure if this might help diagnose the problem, but the code snippet below throws the exception

----------------------------------------------
Unable to cast object of type 'MyNameSpace.DirectoryVersionAttribute' to type 'MyNameSpace.DirectoryVersionAttribute'.
----------------------------------------------

Would cause two apparently similar object types throw an exception on casting.

----------------------------------------------
foreach (Type type in assembly.GetTypes())
{
object[] attributes = type.GetCustomAttributes(false);
foreach (object attribute in attributes)
{
if (attribute.GetType().Name == "DirectoryVersionAttribute")
{
Console.WriteLine("Directory Version: {0}", ((DirectoryVersionAttribute)attribute).Version); // <- Throws Exception here
}
}
}
Hi,

I'm running into one problem with trying to call "Type.GetCustomAttributes(...)" on my reflected code. Basically - I can't trap my own custom attribute - I can only catch / identify system "Custom Attributes" by type. The output below identifies that I can catch the "DefaultMemberAttribute", but I can not catch my own "DirectoryVersionAttribute". Cany anyone throw any light on this as it is driving mad

Thanks in Advance,

- Paul.

------------------------------------------------
System.Reflection.DefaultMemberAttribute
System.Reflection.DefaultMemberAttribute
True
System.AttributeUsageAttribute
System.AttributeUsageAttribute
False
System.AttributeUsageAttribute
System.AttributeUsageAttribute
False
MyNameSpace.DirectoryVersionAttribute
MyNameSpace.DirectoryVersionAttribute
False
Press any key to continue . . .
------------------------------------------------

using System;
namespace MyNameSpace
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
public class DirectoryVersionAttribute : System.Attribute
{
private string version = null;
public DirectoryVersionAttribute(string version)
{
this.version = version;
}
public string Version { get { return this.version; } }
}
}

using MyNameSpace;
namespace AnotherNameSpace
{
[DirectoryVersion("1.00")]
public class DirectoryBuilder_v1_00 : IDirectoryBuilder
{
...
}

private void GetBuilderFile(string fileName)
{
Assembly assembly = Assembly.LoadFrom(fileName);
foreach (Type type in assembly.GetTypes())
{
object[] test = type.GetCustomAttributes(typeof(MyNameSpace.DirectoryVersionAttribute), false);
if (test.Length > 0)
{
Console.WriteLine("Wishful Thinking!"); // <<-- Never gets called!
}
test = type.GetCustomAttributes(typeof(Attribute), false);
if (test.Length > 0)
{
Console.WriteLine(((Attribute)test[0]).TypeId);
Console.WriteLine(((Attribute)test[0]).ToString());
Console.WriteLine(((Attribute)test[0]) is System.Reflection.DefaultMemberAttribute);
Console.WriteLine(((Attribute)test[0]) is MyNameSpace.DirectoryVersionAttribute);
}
}
}
 
G

Guest

Could you try to use reflection on the attribute to get its properties,
"Version" in this case, then use GetValue to fetch it? Basically, use more
reflection instead of casting. I just looked at my old code and that's how I
retrieved values of the custom attribute. Again, hope this helps.
--
Thom


Paul Hadfield said:
I've found the cause, but not sure on what is needed for a clean solution! In my solution I have multiple projects, each compiling into their own DLL's. The console application test harness code, which checks for the occurance of the Custom Attribute is in one class has a reference to the project that contains the attribute (these end up in one directory). The code that uses the custom attribute resides in another project, also with a reference to the project that contains the attribute (these end up in another directory). So the DLL containing the attribute definition is local to each directory - hence what I believe to be the clash.

So this does not work (note, DirectoryVersionAttribute.dll is the same dll, just in two places)

\Dir1\
Test.Exe
DirectoryVersionAttribute.dll
\Dir2\
DirectoryLoader.dll
DirectoryVersionAttribute.dll

However the following (same exe / dll's, just copied) works fine

\Dir3\
Test.Exe
DirectoryLoader.dll
DirectoryVersionAttribute.dll

What is the best solution to this problem, should I start looking into using the GAC ?
Not sure if this might help diagnose the problem, but the code snippet below throws the exception

----------------------------------------------
Unable to cast object of type 'MyNameSpace.DirectoryVersionAttribute' to type 'MyNameSpace.DirectoryVersionAttribute'.
----------------------------------------------

Would cause two apparently similar object types throw an exception on casting.

----------------------------------------------
foreach (Type type in assembly.GetTypes())
{
object[] attributes = type.GetCustomAttributes(false);
foreach (object attribute in attributes)
{
if (attribute.GetType().Name == "DirectoryVersionAttribute")
{
Console.WriteLine("Directory Version: {0}", ((DirectoryVersionAttribute)attribute).Version); // <- Throws Exception here
}
}
}
Hi,

I'm running into one problem with trying to call "Type.GetCustomAttributes(...)" on my reflected code. Basically - I can't trap my own custom attribute - I can only catch / identify system "Custom Attributes" by type. The output below identifies that I can catch the "DefaultMemberAttribute", but I can not catch my own "DirectoryVersionAttribute". Cany anyone throw any light on this as it is driving mad

Thanks in Advance,

- Paul.

------------------------------------------------
System.Reflection.DefaultMemberAttribute
System.Reflection.DefaultMemberAttribute
True
System.AttributeUsageAttribute
System.AttributeUsageAttribute
False
System.AttributeUsageAttribute
System.AttributeUsageAttribute
False
MyNameSpace.DirectoryVersionAttribute
MyNameSpace.DirectoryVersionAttribute
False
Press any key to continue . . .
------------------------------------------------

using System;
namespace MyNameSpace
{
[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
public class DirectoryVersionAttribute : System.Attribute
{
private string version = null;
public DirectoryVersionAttribute(string version)
{
this.version = version;
}
public string Version { get { return this.version; } }
}
}

using MyNameSpace;
namespace AnotherNameSpace
{
[DirectoryVersion("1.00")]
public class DirectoryBuilder_v1_00 : IDirectoryBuilder
{
...
}

private void GetBuilderFile(string fileName)
{
Assembly assembly = Assembly.LoadFrom(fileName);
foreach (Type type in assembly.GetTypes())
{
object[] test = type.GetCustomAttributes(typeof(MyNameSpace.DirectoryVersionAttribute), false);
if (test.Length > 0)
{
Console.WriteLine("Wishful Thinking!"); // <<-- Never gets called!
}
test = type.GetCustomAttributes(typeof(Attribute), false);
if (test.Length > 0)
{
Console.WriteLine(((Attribute)test[0]).TypeId);
Console.WriteLine(((Attribute)test[0]).ToString());
Console.WriteLine(((Attribute)test[0]) is System.Reflection.DefaultMemberAttribute);
Console.WriteLine(((Attribute)test[0]) is MyNameSpace.DirectoryVersionAttribute);
}
}
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top