2
votes

Is it possible to get all the referenced assemblies (within a Unit Test project) that have a custom attribute applied. I use the following code withing my application which works successfully:

var assemblies = System.Web.Compilation.BuildManager.GetReferencedAssemblies().Cast<Assembly>().Where(a => a.GetCustomAttributes(false).OfType<AssemblyCategoryAttribute>().Any()).ToList();

However System.Web.Compilation.BuildManager doesn't work in my test project so I tried:

Assembly.GetExecutingAssembly().GetReferencedAssemblies().Select(a => Assembly.ReflectionOnlyLoad(a.FullName).Where(a => a.GetCustomAttributes(false).OfType<AssemblyCategoryAttribute>().Any()).ToList();

But this threw the error:

It is illegal to reflect on the custom attributes of a Type loaded via ReflectionOnlyGetType (see Assembly.ReflectionOnly) -- use CustomAttributeData instead.

I'd appreciate it if someone could show me how to do this. Thanks

2

2 Answers

5
votes

Since you're getting the referenced assemblies for the currently executing assembly, there is no reason to do a reflection-only load. ReflectionOnlyLoad is for when you want to look at the assemblies but not actually execute them. Since these assemblies are being referenced by the currently executing assembly, there most likely either are or will be loaded into the execution context anyway.

Try just doing:

Assembly
    .GetExecutingAssembly()
    .GetReferencedAssemblies()
    .Select(a => Assembly.Load(a.FullName))
    .Where(a => a.
            .GetCustomAttributes(false)
            .OfType<AssemblyCategoryAttribute>()
            .Any())
    .ToList();

Or better yet:

Assembly
    .GetExecutingAssembly()
    .GetReferencedAssemblies()
    .Select(Assembly.Load)
    .Where(a => a.IsDefined(typeof(AssemblyCategoryAttribute), false))
    .ToList();
2
votes

Look at CustomAttributeData Class

Provides access to custom attribute data for assemblies, modules, types, members and parameters that are loaded into the reflection-only context.

there is a sample c# code there

public static void Main()
{
    Assembly asm = Assembly.ReflectionOnlyLoad("Source");
    Type t = asm.GetType("Test");
    MethodInfo m = t.GetMethod("TestMethod");
    ParameterInfo[] p = m.GetParameters();

    Console.WriteLine("\r\nAttributes for assembly: '{0}'", asm);
    ShowAttributeData(CustomAttributeData.GetCustomAttributes(asm));
    Console.WriteLine("\r\nAttributes for type: '{0}'", t);
    ShowAttributeData(CustomAttributeData.GetCustomAttributes(t));
    Console.WriteLine("\r\nAttributes for member: '{0}'", m);
    ShowAttributeData(CustomAttributeData.GetCustomAttributes(m));
    Console.WriteLine("\r\nAttributes for parameter: '{0}'", p);
    ShowAttributeData(CustomAttributeData.GetCustomAttributes(p[0]));
}

In your case something like this (did not try the code myself):

var assemblies = Assembly.GetExecutingAssembly()
    .GetReferencedAssemblies()
    .Select(a => Assembly.ReflectionOnlyLoad(a.FullName))
    .Select(a => new 
      { Asm = a, 
        CustomAttributeDataList = CustomAttributeData.GetCustomAttributes(a)
      })
    .Where(x => x.CustomAttributeDataList.Any(y => y.AttributeType ==           
         type(AssemblyCategoryAttribute)))
    .Select(x => x.Asm)
    .ToList();