I am designing a scenario where two PostSharp aspects are working with each other. I have one aspect (FirstAspect
in the code below) that is meant to introduce an interface, and then another aspect (SecondAspect
in the code below) is supposed to work with the interface that was introduced by the first aspect.
However, it does not seem that the interface that is introduced by the first aspect is ever available to the second aspect.
Here is the code that I am currently working with:
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 {}
}
When I build, the InvalidOperationException
in the SecondAspect.ProvideAspects
is thrown, as the interface that was introduced by FirstAspect
is not available to SecondAspect
at the time the call is made. That is, even though the interface has been weaved into the MyClass
type, the type as it stands within the current AppDomain as loaded is not marked as having the interface implemented.
What I am looking for is the ability to access and locate all known and weaved interfaces and members on a target element during build time.
I looked into ReflectionSearch
, and this is close to what I am looking for, but it does not appear to account for weaved elements at the time calls into this API are made. For instance, making a call to ReflectionSearch.GetMembersOfType
does not yield the expected IInterface.HelloWorld
on MyClass
(which is introduced by FirstAspect
in the example above).
Is there another API I should be using to access introduced/weaved elements by PostSharp during build-time? Is this even possible?
FirstAspect
custom attributes besieds check for IInterface? Or do you want to apply any aspect to introduced methods as well? – AkeFirstAspect
above), and then apply the aspect to the method that the interface introduces (whether it exists or was introduced, represented bySecondAspect
above). Please let me know if that makes sense! – Direful