У меня есть библиотека классов и решение, расположенное в разных каталогах.
из библиотеки классов я вызываю 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 Похоже, вы в целом довольны моим ответом - даже если только в качестве вдохновения, можете ли вы хотя бы отметить его как принятый ответ?
во что бы то ни стало, только что принял и еще раз спасибо.
«теперь я хочу выполнить оптимизацию, чтобы отфильтровать ссылки и удалить все ссылки на пакеты» — что вы под этим подразумеваете?