Reputation: 14148
In my MiddleTier project in a solution I have Customer classes, one of them defined with Attribute1
public class Customer2
{
public string Name2 { get; set; }
public int Age2 { get; set; }
}
[MyAttribute1]
public class Customer1
{
[MyAttribute1(DefaultValue = "Must Enter Name")]
public string Name { get; set; }
[MyAttribute1(DefaultValue = "Must Enter Age")]
public int Age { get; set; }
}
[AttributeUsage(AttributeTargets.All)]
public class MyAttribute1 : Attribute
{
public string DefaultValue { get; set; }
}
In a separate project, I reference MiddleTier DLL and I want to enumerate through all the classes in this DLL and identify Customer1 class that is associated with Attribute1.
Assembly assembly = Assembly.LoadFrom(@"C:\myfolder\MiddleTier\bin\Debug\MiddleTier.dll");
foreach (Type type in assembly.GetTypes())
{
var attribs = type.GetCustomAttributes(typeof(MyAttribute1), false); <--- problem
if (attribs != null && attribs.Length > 0)
{
....
}
}
I am not getting any attributes back by the GetCustomAttributes call. What am I doing wrong? please help. Thanks
Upvotes: 2
Views: 4796
Reputation: 7088
The problem is that you are actually loading the assembly twice and doing so from two different locations. This results in the assemblies being loaded into two different contexts, which, in turn, results in your types being incompatible. You can easily verify this when you try to run this code (of course, you will need to change the path to the assembly):
foreach (Type type in Assembly.LoadFrom(@"C:\ClassLibrary1.dll").GetTypes())
{
MyAttribute1 attribute = type.GetCustomAttributes(false)
.Cast<MyAttribute1>()
.SingleOrDefault();
if (attribute != null)
{
Console.WriteLine(type.Name);
}
}
That will result in following exception being thrown:
[A]ClassLibrary1.MyAttribute1 cannot be cast to [B]ClassLibrary1.MyAttribute1. Type A originates from 'ClassLibrary1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' in the context 'LoadFrom' at location 'C:\ClassLibrary1.dll'. Type B originates from 'ClassLibrary1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' in the context 'Default' at location 'C:\Users\Nikola\Documents\Visual Studio 2010\Projects\ConsoleApplication12\ConsoleApplication12\bin\Debug\ClassLibrary1.dll'.
So, how to solve it?
You simply need to load the assembly by using Assembly.Load("ClassLibrary1")
. That will make sure that you are working within the single context and your original code will work.
Check out this blogpost which treats upon exactly the same issue you are having. It also may be helpful to read something about load contexts.
Upvotes: 9
Reputation: 13450
var attribs = (MyAttribute1)type.GetCustomAttributes(typeof(MyAttribute1), false)[someIndex];
Upvotes: -2