dotnet-practitioner
dotnet-practitioner

Reputation: 14148

Unable to get attributes back from GetCustomAttributes

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

Answers (2)

Nikola Anusev
Nikola Anusev

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

burning_LEGION
burning_LEGION

Reputation: 13450

var attribs = (MyAttribute1)type.GetCustomAttributes(typeof(MyAttribute1), false)[someIndex];

Upvotes: -2

Related Questions