Всем приветик) Я разобралась с встроенными атрибутами сборок. когда начала разбирать создание собственных атрибутов то все вроде бы хорошо, пока не пошла дальше одной сборки. так вот собственно что хочу узнать как собственноручно созданный атрибут в сборке 1 можно получить из сборки 2, причем референс не указывать, а только через рефлексию. что бы наперед не знать какие есть в каталоге сборки и с камими атрибутами. я пришла не с пустыми руками)) вот то что я уже успела напрограммировать ) СБОРКА ГЛАВНАЯ: PHP: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Reflection; using System.IO; [AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)] public class MyAttribute : System.Attribute { private string NAME; public MyAttribute(string NAME) { this.NAME = NAME; } public virtual string STOKAatributa { get { return NAME; } } } namespace UserAttributeBetween2Assemblys { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { string folder = System.AppDomain.CurrentDomain.BaseDirectory; string[] files = Directory.GetFiles(folder, "*.dll"); foreach (string file in files) { Assembly asm = Assembly.LoadFile(file); MyAttribute adAttr = (MyAttribute)Attribute.GetCustomAttribute(asm, typeof(MyAttribute)); MessageBox.Show(adAttr.STOKAatributa); } } } } и инфо о сборке PHP: using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; [assembly: MyAttribute("MAIN FORM")] и теперь сборка с которой хочу вытащить атрибут и вывести в главной программе. PHP: using System; using System.Collections.Generic; using System.Linq; using System.Text; [AttributeUsage(AttributeTargets.All, Inherited = false, AllowMultiple = true)] public class MyAttribute : System.Attribute { public string NAME; public MyAttribute(string NAME) { this.NAME = NAME; } public virtual string STOKAatributa { get { return NAME; } } } namespace sborka { public class classOfSborka { } } и информация о этой сборке PHP: [assembly: MyAttribute("ТО ЧТО НУЖНО ВЫВЕСТИ В ГЛАВНОЙ ПРОГЕ")] и теперь подскажите мне пожалуйста почему не работает кусок кода MyAttribute adAttr = (MyAttribute)Attribute.GetCustomAttribute(asm, typeof(MyAttribute)); подскажите как мне получить ту строчку.. я не знаю дальше что писать.. спасибо)
Я правильно понял что в обоих сборках у вас определен один и тот же класс атрибута? Если в сборках Asm1 и Asm2 определены полностью идентичные классы с одинаковыми названиями и набором членов это не значит что это один и тот же класс. Т.е. привести Asm1.MyAttribute к Asm2.MyAttribute не получится. По-этому атрибут и не находится, т.к. ищет не тот тип. В общем случае получить список классов-атрибутов определенных в сборке можно так: Code: var attrs = Assembly.LoadFrom("foo.dll") .GetTypes() .Where(t => t.IsSubclassOf(typeof(Attribute))); Получить тип (System.Type) атрибута с заранее известным именем так: Code: var myAttr = Assembly.LoadFrom("foo.dll") .GetTypes() .Where(t => t.IsSubclassOf(typeof(Attribute))) .FirstOrDefault( attr => attr.Name == "MyAttribute"); Либо если упростить: Code: var myAttr = Assembly.LoadFrom("foo.dll") .GetType("MyAttribute"); И соответственно передавать в метод GetCustomAttribute полученный ранее тип. Чтобы получить "строчку" можно написать так: Code: string name = ((MyAttribute)Attribute.GetCustomAttribute(asm, myAttr)).STOKAatributa;
ой спасибо большое сейчас попробую обязательно. при таком подходе как вы предложили мне не нужно теперь создавать такой же атрибут для главной сборки? так как он там в принципе не нужен совсем.
Нет, нужно всего лишь чтобы атрибут был пабличным, и знать его название, а далее вытягивать его тип с помощью reflection'a
не работает то что Вы предожили... смотрите почему. я с главной сборки которая читает, убрала атрибут, что бы его там небыло. ведь есть же сборки с разными атрибутами и на всех не напишешь наперед... так вот оставила только такой код PHP: private void button1_Click(object sender, EventArgs e) { string folder = System.AppDomain.CurrentDomain.BaseDirectory; string[] files = Directory.GetFiles(folder, "*.dll"); foreach (string file in files) { Assembly asm = Assembly.LoadFile(file); var myAttr = Assembly.LoadFrom(file).GetType("MyAttribute"); string name = ((MyAttribute)Attribute.GetCustomAttribute(asm, myAttr)).STOKAatributa; } } ошибка в string name = ((MyAttribute)Attribute.GetCustomAttribute(asm, myAttr)).STOKAatributa; так как я убрала с этой (главной) сборки атрибут. атрибут остался только в сборке к которой подключаемся. в главной сборке только знаем что имя атрибута MyAttribute и все. ну я думаю по логике так же правильнее, чем писать для главной сборки еще раз такой же атрибут, только потому что это нужно для того что бы получить атрибут другой сборки... а такой вариант работать не будет так как в кусочке кода PHP: string name = ((MyAttribute)Attribute.GetCustomAttribute(asm, myAttr)).STOKAatributa; неизвестно что такое MyAttribute и STOKAatributa.... я уже и сама запуталась что к чему... если этот атрибут использовать в сборке которую он и описует, то проблем нет.. и я тут сама разобралась. а для передачи атрибутов между сборками я не знаю что применить... помогите понять) спасибо.
Также с помощью рефлексии, только нужно еще знать имя свойства: PHP: // загружаем сборку с именем file Assembly asm = Assembly.LoadFile(file); // дважды загружать сборку кстати не нужно // получаем тип атрибута var myAttrType = asm.GetType("MyAttribute"); // тут понадобится получить объект атрибута var attrObj = Attribute.GetCustomAttribute(asm, myAttrType); string name = (string)myAttrType.GetType().GetProperty("STOKAatributa").GetValue(attrObj, null);
Вот полностью рабочий пример, только я не создавал свою сборку с атрибутом а просто взял системную. Но смысл остается прежним - я получил значение свойства атрибута внешней сборки: PHP: static void Main(string[] args) { // зашружаем сборку var asm = Assembly.Load("mscorlib.dll"); // получаем тип атрибута var attrType = asm.GetType("System.CLSCompliantAttribute"); // получаем экземпляр атрибута var attrObj = Attribute.GetCustomAttribute(asm, attrType); // заранее зная тип и имя свойства получаем его значение bool b = (bool) attrType.GetProperty("IsCompliant").GetValue(attrObj, null); Console.WriteLine(b); }
Спасибо. Действительно так заработало. теперь сама разберусь глубже в коде что бы тема не прошла мимо)