EADever Ответов: 3

Как получить весь класс с помощью пользовательского атрибута


Привет.
у меня есть атрибут расширения класса AIName, подобный этому:

public class AIName : Attribute
    {
        /// <summary>
        /// Return name of AI
        /// </summary>
        /// <returns></returns>
        private string name;
        public AIName(string name)
        {
            this.name = name;
        }
        public string GetAIName()
        {
            return name;
        }
    }



и мало кто из классов использует пользовательский атрибут, подобный этому:
[AIName("aggressive")]
    public class AggressiveNpcAI2 : GeneralNpcAI2
    {
    }

[AIName("npc")]
    public class NpcAI2 : AITemplate
    {
    }


Поэтому я хотел бы получить все пользовательские атрибуты, где классы используют атрибут AIName.

Что я уже пробовал:

Я попробовал этот код ниже, но он просто может получить 1 класс, который я даю только имя класса.

public void Init()
        {
            Type type = typeof(AggressiveNpcAI2);
            object[] attributes = type.GetCustomAttributes(true);
            foreach (object attribute in attributes)
            {
                AIName da = attribute as AIName;
                if (da != null)
                    Console.WriteLine("AI Name: {0}", da.GetAIName());
                else
                    Console.WriteLine();
            }
        }

Simon_Whale

Существует ли только один атрибут для каждого класса?

EADever

Да, только один атрибут на класс.

3 Ответов

Рейтинг:
5

Simon_Whale

Чтобы добавить к тому, что дал Грифф

Assembly asm = Assembly.GetExecutingAssembly();
foreach(Type type in asm.GetTypes())
{
  //Now if your classes are in a different folder in the same assembly then
  //you will need to specify the full name space address for example
  //"projectName.Classes" (I have assumed that you have a folder in the app called Classes)
  if(type.Namespace == "full namespace address here")
  {
    //do what is needed here
  }
}


если вам нужно загрузить файлы из внешней сборки, измените первую строку на

Assembly asm - Assembly.LoadFromFile("path to dll");


отражение-загрузка DLL во время выполнения в C# - переполнение стека[^]


Рейтинг:
26

OriginalGriff

Если вы можете сделать это для одного именованного типа, то вы можете сделать это для всех типов в вашей сборке. Это будет список их всех:

Assembly myAssembly = Assembly.GetExecutingAssembly();
Type[] types = myAssembly.GetTypes();
foreach (Type type in types)
    {
    Console.WriteLine(type.FullName);
    }
Таким образом, вы можете объединить это с вашим кодом, чтобы найти их все.


EADever

не могли бы вы рассказать подробнее?

OriginalGriff

Какие еще подробности вам нужны?
У вас есть код, который вы написали, чтобы проверить, украшен ли определенный тип вашим атрибутом, и я дал вам код, чтобы найти все типы в вашей сборке.
Так в чем же проблема с объединением двух битов кода?

Рейтинг:
1

EADever

Спасибо @OriginalGriff за ваше предложение.
Я хорошо выполнил свой код и его работу:

Assembly myAssembly = Assembly.GetExecutingAssembly();
            Type[] types = myAssembly.GetTypes();
            foreach (Type typeA in types)
            {
                foreach (object attribute in typeA.GetCustomAttributes(true))
                {
                    AIName da = attribute as AIName;
                    if (da != null)
                    {
                        Add<AggressiveNpcAI2>(da.GetAIName());
                        Console.WriteLine("AI Name: {0}", da.GetAIName());
                    }
                }
            }