问题
Can't seem to find any useful guide on how to reproduce the functionality currently provided by a TypeInterceptor in my codebase when upgrading from StructureMap 2 to version 3 (can't upgrade to v4 as we aren't using .NET 4.6 yet).
Essentially what the interceptor does is this:
public class TheInterceptor : TypeInterceptor
{
private Dictionary<string, string> typesToIntercept;
public TheInterceptor(IDictionary<string, string> typesToIntercept)
{
// Passed in on ctor, comes from XML configuration section.
this.typesToIntercept = typesToIntercept;
}
public object Process(object target, StructureMap.IContext ctx)
{
var typedTarget = target as BaseType;
var key = target.GetType().FullName;
if (typedTarget == null || !typesToIntercept.ContainsKey(key))
{
return target;
}
var propertyOverrideType = typesToIntercept[key];
typedTarget.BaseProperty = ctx.GetInstance<IBaseInterface>(propertyOverrideType);
return typedTarget;
}
}
So we're basically maintaining a dictionary where the key is the type we want to intercept and the value is a specific type that implements a known interface, that we want to set on a property of the intercepted object.
FWIW I didn't write the original code, I just can't figure out what the correct way of mirroring this behaviour in StructureMap 3 would be. I feel like it's something that could be done without an interceptor, but I believe it was implemented like this so that this behaviour could be used across multiple sites (it's in a shared library) without each site having to explicitly deal with the interception behaviour, so if possible I would like to retain this usage.
回答1:
So I eventually figured this out by trial-and-error. What you need is an ActivatorInterceptor and use the Action delegate to perform the logic that previously would have been inside the Process method of the TypeInterceptor. So from my code snippet above, it becomes:
public class InterceptorPolicy : IInterceptorPolicy
{
private readonly IDictionary<string, string> typesToIntercept;
public InterceptorPolicy(IDictionary<string, string> types)
{
this.typesToIntercept = types;
}
public IEnumerable<IInterceptor> DetermineInterceptors(Type pluginType, Instance instance)
{
if (instance.ReturnedType.IsSubclassOf(typeof(BaseType)))
{
yield return new ActivatorInterceptor<BaseType>((ctx, x) => this.Activate(ctx, x));
}
}
private void Activate(IContext ctx, BaseType instance)
{
var key = instance.GetType().FullName;
if (this.typesToIntercept.ContainsKey(key))
{
var propertyOverrideType = this.typesToIntercept[key];
instance.BaseProperty = ctx.GetInstance<IBaseInterface>(propertyOverrideType);
}
}
}
来源:https://stackoverflow.com/questions/36815124/typeinterceptor-replacement-for-structuremap-3