문제

I'm trying to do some attribute-based interception using structuremap but I'm struggling to tie up the last loose ends.

I have a custom Registry that scans my assemblies and in this Registry I have defined the following ITypeInterceptor whose purpose it is to match types decorated with the given attribute and then apply the interceptor if matched. The class is defined as such:

public class AttributeMatchTypeInterceptor<TAttribute, TInterceptor> 
   : TypeInterceptor 
   where TAttribute : Attribute 
   where TInterceptor : IInterceptor
{
    private readonly ProxyGenerator m_proxyGeneration = new ProxyGenerator();

    public object Process(object target, IContext context)
    {
        return m_proxyGeneration.CreateInterfaceProxyWithTarget(target, ObjectFactory.GetInstance<TInterceptor>());
    }

    public bool MatchesType(Type type)
    {
        return type.GetCustomAttributes(typeof (TAttribute), true).Length > 0;
    }
}

//Usage
[Transactional]
public class OrderProcessor : IOrderProcessor{
}
...   
public class MyRegistry : Registry{
    public MyRegistry()
    {
         RegisterInterceptor(
             new AttributeMatchTypeInterceptor<TransactionalAttribute, TransactionInterceptor>());
         ...
    }
}

I'm using DynamicProxy from the Castle.Core to create the interceptors, but my problem is that the object returned from the CreateInterfaceProxyWithTarget(...) call does not implement the interface that triggered the creation of the target instance in structuremap (i.e IOrderProcessor in example above). I was hoping that the IContext parameter would reveal this interface, but I can only seem to get a hold of the concrete type (i.e. OrderProcessor in example above).

I'm looking for guidance on how to have this scenario work, either by calling the ProxyGenerator to return an instance that implements all interfaces as the target instance, by obtaining the requested interface from structuremap or through some other mechanism.

도움이 되었습니까?

해결책

I actually got something working with a slight caveat so I'll just post this as the answer. The trick was to obtain the interface and pass that into the CreateInterfaceProxyWithTarget. My only problem was that I could not find a way to query the IContext about which interface it was currently resolving so I ended up just looking up the first interface on the target which worked for me. See code below

public class AttributeMatchTypeInterceptor<TAttribute, TInterceptor> : 
    TypeInterceptor
    where TAttribute : Attribute 
    where TInterceptor : IInterceptor
{
    private readonly ProxyGenerator m_proxyGeneration = new ProxyGenerator();

    public object Process(object target, IContext context)
    {
        //NOTE: can't query IContext for actual interface
        Type interfaceType = target.GetType().GetInterfaces().First(); 
        return m_proxyGeneration.CreateInterfaceProxyWithTarget(
            interfaceType, 
            target, 
            ObjectFactory.GetInstance<TInterceptor>());
    }

    public bool MatchesType(Type type)
    {
        return type.GetCustomAttributes(typeof (TAttribute), true).Length > 0;
    }
}

Hope this helps someone

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top