У меня есть библиотека классов и решение, расположенное в разных каталогах.
из библиотеки классов я вызываю GetCallingAssembly, который возвращает исполняемый файл из решения, за которым следует вызовAssembly.GetReferencedAssemblies, который возвращает ссылки, теперь я хочу выполнить оптимизацию, чтобы отфильтровать ссылки и удалить все ссылки на пакеты, стремясь найти определенный тип.
Примечание. Я не хочу зависеть от свойства Name ссылок.
Что такое AggregateRoot
в этом контексте?
Не публикуйте изображения кода. Почтовый индекс.
@Dai Я имею в виду фильтрацию referencedAssemblies для удаления ссылок на пакеты. в настоящее время referencedAssemblies представляет собой список всех сборок, на которые ссылается вызывающая сборка, включая сборки Microsoft и AspNetCore, которые я хочу отфильтровать для оптимизации foreach.
@Dai AggregateRoot — это базовый класс моего агрегатного типа, который я хочу найти.
@Fildor Я думал, что это может помочь лучше понять мою цель, идея проста, поскольку я хочу посмотреть, сможем ли мы различать ссылки на пакет и проект при вызове GetReferencedAssemblies.
@SarwanSurchi PackageReferences управляется вашей системой сборки (MSBuild), ссылки на сборки — единственное, о чем заботится csc.exe
. PackageReferences обычно приводит к ссылке на сборку (но не всегда). Это не вариант «или-или».
@Dai так нет возможности узнать какая сборка из полученных мною, проще говоря, созданная мной, а какая сторонняя?
@SarwanSurchi Я не знаю, о чем вы говорите - в отношении CLR не существует такого понятия, как «сторонняя сборка».
@Dai, как искать тип в ответ на вызов метода из вашей сборки? ну, чтобы помочь нам обоим понять контекст, первое, что вы делаете, это вызываете сборку, а затем получаете сборки, на которые ссылаются, против вызова, и в конечном итоге у вас есть куча сборок, в которых одна из них содержит мой тип, проблема здесь в загрузке типов каждого сборка не влияет на производительность, необходим фильтр для удаления таких сборок, как Microsoft.Extensions.DependencyInjection, Microsoft.Extensions.Logging, Microsoft.AspNetCore и т. д. Надеюсь, теперь вы поняли мою проблему :)
«Ну, чтобы помочь нам обоим понять контекст, первое, что вы делаете, это вызываете сборку, а затем получаете сборки, на которые ссылаются, против вызова, и в конечном итоге вы получаете кучу сборок, в которых одна из них содержит мой тип», - Нет, это не так. способ сделать это. Вместо этого я предлагаю вам перечислить типы из всех загруженных сборок в текущем AppDomain
— нет необходимости перемещаться по графу ссылок на сборки.
AppDomain не поможет, поскольку текущая сборка не ссылается на вызывающую сборку.
@SarwanSurchi ...Я думаю, ты неправильно понимаешь, что такое AppDomain
.
правда, моя ошибка, хотя для сборки в AppDomain требуется ссылка.
... если вы просто хотите найти все типы во всех загруженных сборках, производных от вашего типа AggregateRoot
, без поиска сборок, которые не могут содержать подкласс, тогда все, что вам нужно, это:
public static IEnumerable<Type> GetAllTypesDerivedFromAggregateRoot()
{
Assembly[] asses = AppDomain.Current.GetAssemblies();
Type typeofRoot = typeof(AggregateRoot);
AssemblyName mustReferenceThisAssembly = typeofRoot.Assembly.GetName();
List<Assembly> candidates = asses
.Where( ass => ass
.GetReferencedAssemblies()
.Any( ra => AssemblyName.ReferenceMatches( reference: ra, definition: mustReferenceThisAssembly ) )
)
.ToList();
foreach( Assembly candidate in candidates )
{
Type[] types = candidate.GetTypes();
foreach( Type t in types )
{
if ( typeofRoot.IsAssignableFrom( t ) ) yield return t;
}
}
}
Ты справился, @Dai, спасибо. не знал, что AssemblyName.ReferenceMatchesDefinition() существует и это все, что мне нужно. однако не думаете ли вы (в моем случае) лучше использовать вызывающую программу вместо AppDomain, что приводит к меньшему количеству сборок, с которыми приходится иметь дело? и вот мой взлом кода, если вам интересно. var ideals = caller.GetReferencedAssemblies().Where(x => Assembly.Load(x).GetReferencedAssemblies() .Any(x => AssemblyName.ReferenceMatchesDefinition(x, mustReferenceAssembly)));
@SarwanSurchi "не думаешь ли ты (в моем случае) использовать вызывающую программу вместо AppDomain, что приводит к меньшему количеству сборок, с которыми приходится иметь дело?" - Нет, потому что, используя ваш подход, вы не получаете полного представления о своей программе.
ну, у меня есть сборка вызывающего объекта, которая запустила метод, первое, что я делаю, это проверяю, находится ли мой тип в самой сборке вызывающего объекта для оптимизации. если нет, то я использую вызывающую программу для получения ссылок, которые удовлетворяют условию, должны ссылаться на сборку агрегатного корня. более того, большое спасибо, это было здорово.
@SarwanSurchi Другая причина: ваш подход просто не будет работать, если между реальным вызывающим объектом и вашей сборкой находится прокси-сборка или код, сгенерированный во время выполнения (например, такой, который мы получаем с Entity Framework, Linq и т. д.).
что ж, будем надеяться, что со мной этого не произойдет (хотя я не уверен, насколько это распространено), не хочу иметь дело со сложностями на этом уровне и идти глубже.
В конце концов, не уверен, что вам интересно, но если да, то вызывающим объектом является API с несколькими библиотеками классов, вызывающим расширение AddEventSourcing, которое запускает то, что мы обсуждали, а AddEventSourcing находится в отдельном решении, которое является моей структурой поиска событий. Теперь причина, по которой мое расширение не является универсальным, когда я просто отправляю свой агрегат, не заключается в том, что клиенты заставляют указывать агрегат. вместо этого я нахожу дополнительные агрегаты и преобразую свои общие репозитории в IoC.
Универсальные репозитории @SarwanSurchi — это антишаблон. Не используйте их.
Согласитесь, с ними сложно справиться, спасибо за урок, но какая практика способствует этому? наверное состав? @Дай
@SarwanSurchi Композиция не имеет к этому никакого отношения. Речь идет о том, чтобы не тратить время на добавление абстракций, которые не приносят никакой пользы и только создают антиработу в долгосрочной перспективе.
ну, в моей ситуации мне нужны дженерики для достижения моей цели, пока не могу придумать лучшего способа.
@SarwanSurchi Похоже, вы в целом довольны моим ответом - даже если только в качестве вдохновения, можете ли вы хотя бы отметить его как принятый ответ?
во что бы то ни стало, только что принял и еще раз спасибо.
«теперь я хочу выполнить оптимизацию, чтобы отфильтровать ссылки и удалить все ссылки на пакеты» — что вы под этим подразумеваете?