2009-03-16 3 views
2

Der folgende Code erkennt erfolgreich interne Klassen, die mit meiner benutzerdefinierten „Module“ Attribut versehen sind, ich die Versammlung wie folgt laden:Wie erkennt C# benutzerdefinierte Attribute in externen DLLs?

Assembly assembly = Assembly.GetExecutingAssembly(); 

Allerdings, wenn ich in einem externes Modul laden und schauen durch seine Klassen, findet es die Klassen in der Außenmontage aber nicht erkennt die benutzerdefinierte Attribute:

Assembly assembly = Assembly.LoadFrom(@"c:\tests\modules\CustomModules.dll"); 

Was muss ich angeben, damit C# benutzerdefinierte Attribute in externen .dlls genauso erkennt wie bei den internen Klassen?

Hier ist der Code, der durch erfolgreich ausgeführt wird und erkennt interne Klassen mit meinem „Modul“ Attribut dekoriert:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Reflection; 

namespace DynamicAssembly2 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var modules = from t in GetModules() 
          select t; 
      foreach (var module in modules) 
      { 
       ModuleAttribute[] moduleAttributes = GetModuleAttributes(module); 
       Console.WriteLine(module.FullName); 
       foreach (var moduleAttribute in moduleAttributes) 
       { 
        Console.WriteLine(moduleAttribute.Description); 
       } 
      } 
      Console.ReadLine(); 
     } 

     public static IEnumerable<Type> GetModules() 
     { 
      //Assembly assembly = Assembly.LoadFrom(@"c:\tests\modules\CustomModules.dll"); 
      Assembly assembly = Assembly.GetExecutingAssembly(); 

      return GetAssemblyClasses(assembly) 
       .Where((Type type) => {return IsAModule(type);}); 
     } 

     public static IEnumerable<Type> GetAssemblyClasses(Assembly assembly) 
     { 
      foreach (Type type in assembly.GetTypes()) 
      { 
       Console.WriteLine(type.FullName); 
       yield return type; 
      } 
     } 

     public static bool IsAModule(Type type) 
     { 
      return GetModuleAttribute(type) != null; 
     } 

     public static ModuleAttribute GetModuleAttribute(Type type) 
     { 
      ModuleAttribute[] moduleAttributes = GetModuleAttributes(type); 
      Console.WriteLine(moduleAttributes.Length); 
      if (moduleAttributes != null && moduleAttributes.Length != 0) 
       return moduleAttributes[0]; 
      return null; 
     } 

     public static ModuleAttribute[] GetModuleAttributes(Type type) 
     { 
      return (ModuleAttribute[])type.GetCustomAttributes(typeof(ModuleAttribute), true); 
     } 

    } 
} 

Hier Attribut meine benutzerdefinierte Mdoule ist:

using System; 

namespace DynamicAssembly2 
{ 
    [AttributeUsage(AttributeTargets.Class)] 
    public class ModuleAttribute : Attribute 
    { 
     public string Description { get; set; } 
    } 
} 

Hier ist ein eigener Modul:

Antwort

4

Wie viele Instanzen des ModuleAttr ibute class haben Sie in Ihren Baugruppen definiert?

Es sieht so aus, als ob Sie eine in DynamicAssembly2 und eine in CustomModules haben ... in diesem Fall sind sie verschiedene Typen.

Ihr Code in DynamicAssembly2 sollte die in CustomModules definierte Attributklasse verwenden (oder beide Assemblys sollten das Attribut von einer dritten Assembly laden).

+0

Ja, genau, ich hatte einen in DynamicAssembly2 und einen in CustomModules. Ich habe ein neues Projekt mit dem Namen "CustomAttributes" erstellt und dieses aus beiden Projekten referenziert, dann hat es funktioniert. Großartig, danke. –

2

Ich bin mir ziemlich sicher, dass es nicht unterscheidet ... Sind Sie sicher, dass Sie nach dem richtigen Attribut fragen? Solange beide Projekte auf die selbeModuleAttribute verweisen, sollte typeof(ModuleAttribute) funktionieren. Andernfalls müssen Sie zuerst das Type des gewünschten Attributs (von Assembly.GetType()) finden und dieses verwenden, wenn Sie GetCustomAttributes aufrufen.

1

Aloha

ich Ihren Code getestet habe, kann es aber nicht kompilieren, weil der Typ ModuleAttribute muss sowohl im Hauptprogramm und der externen dll bekannt sein. Ich nahm an, dass es keine Referenzen gab.

Ich habe es durch die Einführung einer Referenz zu arbeiten.

Hier ist die Klasse. Diese Anordnung enthält einen Verweis auf DynamicAssembly

using System;  

namespace DynamicAssembly2 
{ 
    [DynamicAssembly.Module(Description = "This is the main customer class.")] 
    public class Customers 
    { 
    } 
} 

Hier ist der Code in DynamicAssembly:

using System.Reflection; 

namespace DynamicAssembly 
{ 
    [AttributeUsage(AttributeTargets.Class)] 
    public class ModuleAttribute : Attribute 
    { 
     public string Description { get; set; } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      var modules = from t in GetModules() 
          select t; 
      foreach (var module in modules) 
      { 
       ModuleAttribute[] moduleAttributes = GetModuleAttributes(module); 
       Console.WriteLine(module.FullName); 
       foreach (var moduleAttribute in moduleAttributes) 
       { 
        Console.WriteLine(moduleAttribute.Description); 
       } 
      } 
      Console.ReadLine(); 
     } 

     public static IEnumerable<Type> GetModules() 
     { 
      Assembly assembly = Assembly.LoadFrom(@"C:\Temp\ClassLibrary1\bin\Debug\ClassLibrary1.dll"); 

      return GetAssemblyClasses(assembly) 
       .Where((Type type) => { return IsAModule(type); }); 
     } 

     public static IEnumerable<Type> GetAssemblyClasses(Assembly assembly) 
     { 
      foreach (Type type in assembly.GetTypes()) 
      { 
       yield return type; 
      } 
     } 

     public static bool IsAModule(Type type) 
     { 
      return GetModuleAttribute(type) != null; 
     } 

     public static ModuleAttribute GetModuleAttribute(Type type) 
     { 
      ModuleAttribute[] moduleAttributes = GetModuleAttributes(type); 
      Console.WriteLine(moduleAttributes.Length); 
      if (moduleAttributes != null && moduleAttributes.Length != 0) 
       return moduleAttributes[0]; 
      return null; 
     } 

     public static ModuleAttribute[] GetModuleAttributes(Type type) 
     { 
      return (ModuleAttribute[])type.GetCustomAttributes(typeof(ModuleAttribute), true); 
     } 

    } 
} 
0

ich hatte das gleiche Problem. Wenn das Attribut in einem internen * cs definiert wäre, könnte ich das Attribut erhalten, aber wenn es in einer externen DLL definiert wäre, würde ich nur NULL bekommen, wenn ich danach gefragt habe (kein Fehler), aber auch keinen Linker-Fehler.

Anscheinend wird ein benutzerdefiniertes Attribut, das in einer DLL definiert ist, und dasselbe in lokalem Code (* cs) definierte Attribut in eine Anwendung ohne Warnungen über mehrere Definitionen kompiliert (die Namensräume sind identisch). Ich löschte den lokalen Code (* cs) und reparierte die Referenzen und es funktionierte.

Verwandte Themen