I want to register all classes that implement a specific interface in Unity using convention WithMappings.FromMatchingInterface. In addition, I want all registered objects to be intercepted using the interface interception behavior. The problem is that Unity also registers mappings between specific classes, and when these classes are enabled, an exception is thrown with the message:
"[type] is not intercepted"
I understand that solving an object using a particular type of class is not best practice, but I wonder why Unity automatically adds mappings for the interface → specific class, as well as the specific class → of a particular class when registering by convention? This means that it will never work if you add an interface hook and allow the use of a specific type.
My desired result for this would be that Unity did not add specific types -> specific types of mappings when registering by convention and providing it with an interceptor interface, so we could resolve the class using its specific type, if we wanted, we just would not receive an interception.
I do not want to use VirtualMethodInterceptor, because I do not want to impose changes in the classes so that the interception works, this includes inheritance from MarshalByRef. I also want to avoid the individual registration of all objects.
My questions are, therefore, how do I register only interface mappings when registering by agreement?
Update : registering classes individually gives the same problem, therefore, it is assumed that after registering an object using the interface, it cannot be resolved using a specific type.
New registration code:
container.RegisterType<ISomeService, SomeService>(new InjectionMember[]
{
new Interceptor<InterfaceInterceptor>(),
new InterceptionBehavior<TraceInterceptor>()
});
container.RegisterType<ISomeRepository, SomeRepository>(new InjectionMember[]
{
new Interceptor<InterfaceInterceptor>(),
new InterceptionBehavior<TraceInterceptor>()
});
2 , , , . InterfaceInterceptor .
foreach (var type in types)
{
container
.Configure<Interception>()
.SetDefaultInterceptorFor(type.GetInterface("I" + type.Name), new InterfaceInterceptor());
}
, :
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.InterceptionExtension;
using System;
using System.Diagnostics;
using System.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
IUnityContainer container = new UnityContainer();
container.AddNewExtension<Interception>();
var types = AllClasses.FromAssemblies(typeof(ISomeService).Assembly).Where(type => type == typeof(SomeService) || type == typeof(SomeRepository));
container.RegisterTypes(
types,
WithMappings.FromMatchingInterface,
getLifetimeManager: WithLifetime.ContainerControlled,
getInjectionMembers: c => new InjectionMember[]
{
new Interceptor<InterfaceInterceptor>(),
new InterceptionBehavior<TraceInterceptor>()
});
var someService1 = container.Resolve<ISomeService>();
someService1.SomeServiceMethod("Hello from main method");
var someService2 = container.Resolve<SomeService>();
someService2.SomeServiceMethod("This will never be shown due to a hissy fit thrown by the container about the concrete SomeService is not interceptable.");
}
}
public class TraceInterceptor : IInterceptionBehavior
{
public System.Collections.Generic.IEnumerable<System.Type> GetRequiredInterfaces()
{
return Type.EmptyTypes;
}
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
Trace.WriteLine(string.Format("Hello from trace interception behavior for type [{0}]!", input.Target.GetType().FullName));
return getNext().Invoke(input, getNext);
}
public bool WillExecute
{
get { return true; }
}
}
public interface ISomeService
{
string SomeServiceMethod(string someParameter);
}
public class SomeService : ISomeService
{
private ISomeRepository _someRepository;
public SomeService(ISomeRepository someRepository)
{
_someRepository = someRepository;
}
public string SomeServiceMethod(string someParameter)
{
return _someRepository.SomeRepositoryMethod(someParameter);
}
}
public interface ISomeRepository
{
string SomeRepositoryMethod(string someParameter);
}
public class SomeRepository : ISomeRepository
{
public string SomeRepositoryMethod(string someParameter)
{
Trace.WriteLine(someParameter);
return "Hello from repository!";
}
}
}