Я разрабатываю сценарий, в котором два аспекта PostSharp работают друг с другом. У меня есть один аспект (FirstAspect
в коде ниже), который предназначен для введения интерфейса, а затем другой аспект (SecondAspect
в коде ниже) должен работать с интерфейсом, который был введен первым аспектом.Возможно ли получить доступ к введенным/сотканным интерфейсам и членам PostSharp во время сборки?
Однако не кажется, что интерфейс, который представлен первым аспектом, всегда доступен для второго аспекта.
Вот код, который я в настоящее время работает с:
public class Tests
{
[Fact]
public void Verify()
{
// Not really all that significant as the current code does not compile correctly:
var sut = new MyClass();
Assert.True(sut is IInterface);
}
public interface IInterface
{
void HelloWorld();
}
[IntroduceInterface(typeof(IInterface))]
public class FirstAspect : InstanceLevelAspect, IInterface, IAspectProvider
{
public void HelloWorld() {}
public IEnumerable<AspectInstance> ProvideAspects(object targetElement)
{
// Implementing IAspectProvider appears to ensure this aspect is processed first.
// This may be a bug.
// Please see: http://support.sharpcrafters.com/discussions/problems/3365-runtimeinitialize-does-not-follow-ordering-rules#comment_40824072
// for more information.
yield break;
}
}
[AspectTypeDependency(AspectDependencyAction.Order, AspectDependencyPosition.After, typeof(FirstAspect))]
public class SecondAspect : InstanceLevelAspect, IAspectProvider
{
public IEnumerable<AspectInstance> ProvideAspects(object targetElement)
{
var type = (Type)targetElement;
if (!typeof(IInterface).GetTypeInfo().IsAssignableFrom(type))
{
// This is currently being thrown, as MyClass does not implement
// IInterface when the AppDomain is first loaded and initialized:
throw new InvalidOperationException($"Does not implement {typeof(IInterface)}");
}
// How to access the weaved elements from FirstAspect? ...
yield break;
}
}
[FirstAspect, SecondAspect]
class MyClass {}
}
Когда я строю, то InvalidOperationException
в SecondAspect.ProvideAspects
выбрасывается, как интерфейс, который был введен FirstAspect
не доступен для SecondAspect
в то время вызов выполнен. То есть, хотя интерфейс был спрессован в тип MyClass
, тип, поскольку он находится в текущем AppDomain, как загруженный, не отмечен как имеющий реализованный интерфейс.
Что я ищу - это возможность доступа и определения всех известных и переплетенных интерфейсов и элементов на целевом элементе во время сборки.
Я просмотрел ReflectionSearch
, и это близко к тому, что я ищу, но оно не похоже на учет тканных элементов во время вызова этого API. Например, вызов ReflectionSearch.GetMembersOfType
не дает ожидаемого IInterface.HelloWorld
по адресу MyClass
(который представлен в приведенном выше примере FirstAspect
).
Есть ли другой API, который я должен использовать для доступа к введенным/переплетенным элементам PostSharp во время сборки? Возможно ли это?
аспекты PostSharp видят только оригинальные типы и методы, нет способа увидеть сотканные интерфейсы во время сборки. Что вы хотите сделать с введенным интерфейсом в SecondAspect? –
Спасибо за ваш ответ @JakubLinhart. Я хочу убедиться, что определенный интерфейс применяется к моему классу, а затем, как только этот интерфейс применяется, примените к нему какое-либо количество аспектов, как обычно. Похоже, мне нужно выяснить другой способ сделать это? –
Как насчет проверки наличия пользовательских атрибутов 'FirstAspect' для проверки на IInterface? Или вы хотите применить какой-либо аспект к введенным методам? –