инкапсуляция c#: получение типов из другого проекта
Мне нужно немного объяснить, чтобы добраться до проблемы.
У меня есть 3 проекта:
Проект 1 может видеть проекты 2 и 3.
Проект 2 может видеть проект 3.
Project 3-это dll, а остальные-приложения.
Мне пришлось разработать класс с большим количеством подклассов. У всех подклассов есть метод, который объявлен как абстрактный в базе, поэтому они все должны использовать его. Они должны быть распределены во всех проектах, потому что код в methode напрямую взаимодействует с проект.Абстрактные базовые классы находятся в проекте 3, подклассы-в 2 и 1. Вот проблема, которая у меня есть:
Это метод, который я написал:
public static IEnumerable<Type> GetSubClasses(Type typ)
{
IEnumerable<Type> subclasses =
from type in Assembly.GetAssembly(typ).GetTypes()
where type.IsSubclassOf(typ) && !type.IsAbstract
select type;
return subclasses;
}
Я пытаюсь получить все подклассы этого типа, но когда я это делаю, я получаю только подклассы из текущего проекта. Например, если я попытаюсь получить их из проекта 1, я не получу подклассы из проекта 2.
Как мне это сделать? Я знаю, что могу получить ссылку на сборку из проекта 2, но у него нет GetAssembly(тип Т) метод, с помощью которого я получаю все подклассы. Если бы это было то же самое, я просто должен был сделать то же самое там.
Мой второй вопрос: есть ли вообще более простой способ? Это немного.."большой" имея эти классы во многих проектах, возможно, есть решение, чтобы получить их в один. Как я уже сказал, код methode, который они все должны иметь, должен непосредственно взаимодействовать с проектом, в котором они находятся.
3 ответа:
Проблема в том, что вы звоните
Assembly.GetTypes()
. Это дает вам только классы в этой конкретной сборке. Если у вас есть объектыAssembly
для всех трех сборок, вы можете сделать что-то вродеТаким образом, проблема заключается в том, как вы получаете три объектаassem1.GetTypes() .Concat(assem2.GetTypes()) .Concat(assem3.GetTypes())
Assembly
. Из проекта 1 Вы можете просто сказатьvar assem1 = typeof(SomeClassInProj1).Assembly; var assem2 = typeof(SomeClassInProj2).Assembly; var assem3 = typeof(SomeClassInProj3).Assembly;
В проекте, где вы не можете "видеть" другие сборки, вам нужно загрузить их. Смотрите документацию по
Assembly.Load
.
Любой базовый класс или интерфейс не должен знать или заботиться о своих наследниках или участниках. Любое взаимодействие должно быть ограничено абстрактными или виртуальными членами, которые переопределяются.
Аналогичным образом, сборка, экспортирующая открытые типы, не предназначена для того, чтобы знать что-либо об импортерах. Если сделать это с "ранним привязыванием", то получится круговая ссылка.Можно было бы точно отразить все сборки, загруженные в домен приложения, и посмотреть, какие из них наследуются от определенного типа но что вы намерены делать с этой информацией? Вероятно, есть более простой и быстрый способ достичь этого.
Вы должны загрузить все сборки, которые могут содержать типы, которые вы хотите найти, и искать типы, как вы делаете в цикле.
Я сделал что-то вроде этого для получения списка всех классов из сборок в текущей папке приложения bin, которые наследуют от некоторого базового класса:
// load all files from current dir which ends with `.dll` var q = from s in Directory.GetFiles(Directory.GetCurrentDirectory(), "*.dll") select s; var types = q.Select(s => getTypes(s, myBaseType)) .SelectMany(typeList => typeList).ToList();
И функция getTypes:
IEnumerable<Type> getTypes(string filePath, Type baseType) { Assembly a = Assembly.LoadFrom(filePath); return a.GetTypes().Where(t => t.IsSubclassOf(baseType) && !t.IsAbstract); }
Вы должны иметь дело с некоторыми исключениями, такими как
BadImageFormatException
, когда у вас есть dll в папке, которые не являются сборками .net.Другой подход возможно, для настройки списка сборок, которые вы хотите проверить.