I'm trying to develop a custom attribute in order to decorate methods, and when I do that I want them to be "catched" by the attribute so it decides what to do with the exception.
I'm aware of specially two techniques to do this:
- PostSharp
- Enterprise Library Unity
I'd like to avoid the first one, I'd like to go ahead with Unity since we already use Enterprise Library.
So, in order to make this work, I've done the following:
My call handler:
public class LoggingCallHandler : ICallHandler
{
public bool Rethrow
{
get; set;
}
public bool Log
{
get; set;
}
public int Order
{
get; set;
}
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
var result = getNext().Invoke(input, getNext);
if (result.Exception != null)
{
if (this.Rethrow)
throw result.Exception;
if (this.Log)
this.LogException(result.Exception);
}
return result;
}
private void LogException(Exception ex)
{
// Do stuff
}
}
My custom attribute
public class LoggingCallHandlerAttribute : HandlerAttribute
{
private bool rethrow;
private bool log;
public LoggingCallHandlerAttribute(bool rethrow, bool log = false)
{
this.rethrow = rethrow;
this.log = log;
}
public override ICallHandler CreateHandler(IUnityContainer container)
{
return new LoggingCallHandler() { Rethrow = this.rethrow, Log = this.log };
}
}
My class with the method decorated with the attribute
public class TestManager
{
[LoggingCallHandler(false, false)]
public void DoStuff()
{
throw new Exception("TEST");
}
}
When I run the method, no AOP happens.
I'm aware thar Unity may rely or relies at all in containers. But we don't use any of that currently, so we'd like just to decorate a method with the [LoggingCallHandler] attribute and that's it.
If container is really necessary it can be considered but it would be nice to have a single container that fits all purposes (at least for now...).
Is it possible to achieve this?
Thank you guys.
I actively work on NConcern .NET AOP Framework a new open source project. You could try it to do what you need.
Aspect to manage your exception handling
public class ExceptionHandlingAspect : IAspect
{
private void Log(Exception exception)
{
//...
}
public IEnumerable<IAdvice> Advise(MethodInfo method)
{
//advise only if method is tagged.
if (Attribute.IsDefined(method, typeof(LoggingCallHandlerAttribute))
{
//get attribute
var attribute = method.GetCustomAttributes(typeof(LoggingCallHandlerAttribue))[0] as LoggingCallHandlerAttribute;
//describe how yo rewrite method.
yield return Advice.Basic.Arround(invoke =>
{
try { invoke(); } //call original code
catch (Exception e)
{
if (attribute.Rethrow)
{
throw;
}
if (attribute.Log)
{
this.Log(e);
}
}
});
}
}
}
attach aspect to all methods attributed with LoggingCallHandlerAttribute;
Aspect.Weave<ExceptionHandlingAspect>(method => method.IsDefined(typeof(LoggingCallHandlerAttribute), true);
If you don't use Unity container to construct your objects, then the interception (via ICallHandler) will not work.
Such interception depends on Unity to wrap your objects when you create them through the Unity DI container.
PostSharp interception will work even if you don't use a DI container.
If you don't use a DI container, (IMO) it might be better for you to keep things as is and don't introduce a DI container to your code base. See my article here.
You might also want to consider doing interception using DynamicProxy. But this requires you to wrap your objects manually when you create them.
Related
I have two classes: ImportBase.cs (Parent) and ImportFleet.cs (Child) which will in the future import a CSV file. Each child of ImportBase will implement a different implementation of the actual import code.
The approriate child class to use is determined in a Service class where the correct class is instantiated and the import method called. All is going well up until this point.
The problem is that I also want to Dependency Inject some repository classes into ImportBase and it's inherited classes (as I have attempted in the code below):
ImportBase.cs
namespace WebApi.Services.Import.Investments
{
interface IImport
{
public void Import(IFormFile file, int UserId);
}
public abstract class ImportBase : IImport
{
public abstract void Import(IFormFile file, int UserId);
protected List<InvestmentTransactionType> transactionTypes = new();
protected IInvestmentEntityRepository _investmentEntityRepository;
public ImportBase(IInvestmentEntityRepository investmentEntityRepository)
{
_investmentEntityRepository = investmentEntityRepository;
}
}
}
ImportFleet.cs
namespace WebApi.Services.Import.Investments
{
public class ImportFleet : ImportBase
{
public ImportFleet(IInvestmentEntityRepository investmentEntityRepository) : base(investmentEntityRepository)
{
}
public override void Import(IFormFile file, int UserId)
{
}
}
}
InvestmentService.cs
namespace WebApi.Services
{
public interface IInvestmentService
{
public void Import(IFormFile file, int UserId, int InvestmentEntityId);
}
public class InvestmentService: IInvestmentService
{
public void Import(IFormFile file, int UserId, int InvestmentEntityId)
{
IImport importService = null;
string investmentEntity = ImportBase.determineInvestmentEntityFromCsv(file);
switch(investmentEntity)
{
case "fleet":
importService = new ImportFleet(); // problem is here
break;
}
if (importService != null)
{
importService.Import(file, UserId);
}
}
}
}
The problem is the following line:
importService = new ImportKuflink();
Because I only determine which child class to instantiate at run time, I cannot take advantage of DI here.
Under normal circumstances I would make the Import classes a DI based service so all dependencies are available, however I have to create the instance at run time so this I don't think is possible.
Is there a way to accomplish the above?
Here's a simplified version of your code that demonstrates how you can populate an instance of an object from a DI service container.
In your InvestmentService:
Inject the IServiceProvider.
Use the little known utility ActivatorUtilities to get a fully DI'd instance of your object.
Make sure you dispose it properly if it implemenents IDisposable. I've included an async version if you use anything that needs a IAsyncDisposable.
public class InvestmentService : IInvestmentService
{
private IServiceProvider _serviceProvider;
public InvestmentService(IServiceProvider serviceProvider)
{
_serviceProvider = serviceProvider;
//...
}
public Import()
{
IImport? importService = null;
IDisposable? disposable = null;
var importFleet = ActivatorUtilities.CreateInstance<ImportFleet>(_serviceProvider);
if (importFleet is IDisposable)
disposable = importFleet as IDisposable;
importService = importFleet as IImport;
// Do whatever you want to do with it
disposable?.Dispose();
}
public async ValueTask ImportAsync()
{
IImport? importService = null;
IDisposable? disposable = null;
IAsyncDisposable? asyncDisposable = null;
var importFleet = ActivatorUtilities.CreateInstance<ImportFleet>(_serviceProvider);
if (importFleet is IDisposable)
disposable = importFleet as IDisposable;
if (importFleet is IAsyncDisposable)
asyncDisposable = importFleet as IAsyncDisposable;
importService = importFleet as IImport;
// Do whatever you want to do with it
disposable?.Dispose();
if (asyncDisposable is not null)
await asyncDisposable.DisposeAsync();
}
}
Yes, of course there is a way to accomplish this. But I guess the DI container you are using (like from MS) won't help you here.
I've been fiddling with crap like this for like two years so far and still am busy with it. Two years of creating my own IoC framework.
Usual DI/IoC microkernels follow OCP and other really mandatory concepts and patterns. What I've done is leaving one single small door open. I won't bore you with details. The fundamental idea is that a class must be decorated with the appropriate attributes in code, and then is able to call the microkernel within its constructor (which has been called by a simple "var foo = new Barney();") to let an entity be modified like it had been created by the microkernel.
There is no(t yet a) way to hook into the plain new() code. Some cheer this, some don't. I'm with the cheerleaders here. Why? Side-effects.
Imagine this:
public class SomeNumber
{
public int SomeValue { get; private set; }
public SomeNumber()
{
SomeValue = 19;
}
}
Okay? Let's assume you'd modified the new() process by whatever, then another user of your code goes:
Assert.AreEqual(19, someNumberEntity.SomeNumber);
and this code throws an exception, because for whatever reason your modifying code set the number to 7.
Now look at this code (from a unit test):
using System.Reflection;
using Kis.Core.Attributes;
namespace UnitTests_Kis.Core
{
[KisAware]
public class KisAwareSimpleClass
{
[Property(value: 123)]
public int ValueToCheck { get; set; } = 0;
[Property(value: "I am the doctor!")]
public string Name { get; set; } = "";
public KisAwareSimpleClass()
{
var t = this.GetType();
var fqtn = t.FullName;
var ec = new Kis.Core.EntityCreator(Assembly.GetAssembly(t));
ec.ModifyExistingEntity(fullyQualifiedTypeName: fqtn, existingEntity: this);
}
}
}
Clean code isn't always easily readable, but the aspects/attributes will raise coder's awareness.
PS: I posted the unit test code on purpose to show you what's happening.
Short version:
Microkernel.Modify(this);
You can inject a factory which has the services injected into it.
public interface IImportFactory
{
ImportFleet CreateFleetImporter();
}
public class MyImportFactory : IImportFactory
{
private readonly IMyDependency1 _dependency1;
private readonly IMyDependency2 _dependency2;
public MyImportFactory(IMyDependency1 dependency1, IMyDependency2 dependency2)
{
_dependency1 = dependency1;
_dependency2 = dependency2;
}
public ImportFleet CreateFleetImporter()
{
return new ImportFleet(_dependency1, _dependency2);
}
}
Then inject the factory as a dependency in your Service class.
So I have a few instances where I'd like to be able to do this but essentially I'd like to be able to wrap all calls to a Superclass in a derived type. Right now I'm trying to wrap all calls to base method in an Impersonator but I can see other uses for this as well.
An example being
public void CopyFile(string filePath, string destPath)
{
using(var I = new Impersonator("user", ".", "password"))
{
base.CopyFile(string filePath, string destPath);
}
}
Another convenient use might be
public void CopyFile(string filePath, string destPath)
{
try
{
base.CopyFile(string filePath, string destPath);
} catch(Exception e)
{
Log(e.Message);
}
}
Now I'd like to wrap all base calls similarly. Is there a convenient way to do this or do I have to wrap all of these manually?
I'm looking for something like a "foreach baseMethod in Superclass Do This"
Perhaps finding some way to capture incoming calls to the class and wrapping them as an action?
public void ActionWrapper(Action action)
{
try
{
action.Invoke();
} catch(Exception e)
{
Log(e.Message);
}
}
But how would I catch calls to the class in that way?
Honestly this is just to make the class more maintainable and reduce code bloat. I'm open to these or any other approaches.
First, I want to applaud your instinct to deconstruct code this way. Separating concerns like error handling/logging and security/identity from your business logic can do wonders for maintainability.
What you're describing is known as either decoration or interception. Mark Seemann has a good blog post comparing the two approaches in the context of logging.
Without using external tools (like a DI or AOP framework), I think the ActionWrapper method you proposed is a good start. I modified it to show impersonation rather than logging, since I think impersonation is a more interesting use case:
public void ActionWrapper(Action action)
{
using(var I = new Impersonator("user", ".", "password"))
{
action.Invoke();
}
}
So the question is: How to apply this method efficiently?
Let's assume your existing class is:
public class FileCopier
{
public void CopyFile(string filePath, string destPath)
{
// Do stuff
}
}
You could, as you suggested, create a derived class to add impersonation:
public class FileCopierWithImpersonation : FileCopier
{
public void CopyFile(string filePath, string destPath)
=> WithImpersonation(base.CopyFile(filePath, destPath));
public void WithImpersonation(Action action)
{
using(var I = new Impersonator("user", ".", "password"))
{
action.Invoke();
}
}
}
Here, FileCopierWithImpersonation serves as a decorator over FileCopier, implemented via inheritance. The WithImpersonation method serves as an interceptor that can apply an impersonation scope over any method.
That should work well enough, but it forces some compromises in implementation. The base class's methods will all need to be marked as virtual. The child class's constructor might need to pass arguments to the base class. It will be impossible to unit test the child class's logic independently of the base class's logic.
So, you might want to extract an interface (IFileCopier) and apply the decorator using composition rather than inheritance:
public class FileCopierWithImpersonation : IFileCopier
{
private readonly IFileCopier _decoratee;
public FileCopierWithImpersonation(IFileCopier decoratee)
{
// If you don't want to inject the dependency, you could also instantiate
// it here: _decoratee = new FileCopier();
_decoratee = decoratee;
}
public void CopyFile(string filePath, string destPath)
=> WithImpersonation(_decoratee.CopyFile(filePath, destPath));
public void WithImpersonation(Action action)
{
using(var I = new Impersonator("user", ".", "password"))
{
action.Invoke();
}
}
}
If you're using Visual Studio 2019, there's a refactoring option to "Implement Interface through..." that will automatically implement an interface by calling methods of a dependency of the same type. After that, a simple find/replace should be all that's needed to add the interceptor.
You could also look into code generation tools, like T4 Templates to auto-generate the decorators. Beware, though, that T4 is not supported in .NET Core. It looks to be a legacy technology at this point.
From a good design perspective, I would advise not to do this for 2 reasons:
If catching exception is the sole purpose, then don't do it. Catching and swallowing system exceptions is a bad practice
If you want to do some pre-setup or post-processing on every method of base then may be you should choose composition rather than inheritance here.
However, if you have made up your mind then using an array of delegates can solve your problem.
class Derived : Base
{
private Action[] AllActions;
public Derived()
{
AllActions = new Action[]
{
base.DoSomething1,
base.DoSomething2,
base.DoSomethingMore
};
}
public ActionWrapper(int index)
{
try
{
AllActions[index].Invoke();
} catch(Exception e)
{
Log(e.Message);
}
}
}
For simplicity I have used an array. Use a dictionary to keep a key for each base class method.
I see AOP has been suggested but not expanded upon, so I will attempt to cover it then.
I am assuming you are open to making your base class methods virtual. In this case using a Castle DynamicProxy might give you the flexibility you are after. It will allow you to not only inject code before and after parent method execution, but also change input/output parameters depending on your business requirements.
Here's an artist's impression on what your class might look like should you opt for it:
public class FileCopier
{
public virtual void CopyFile(string filePath, string destPath)
{
// do things here
}
}
public class ImpersonationInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
using (var I = new Impersonator("user", ".", "password"))
{
invocation.Proceed();
}
}
}
public class LoggingInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
try
{
invocation.Proceed();
}
catch (Exception e)
{
Log(e.Message);
}
}
}
public class CustomProxyGenerationHook : IProxyGenerationHook
{
public void MethodsInspected() {}
public void NonProxyableMemberNotification(Type type, MemberInfo memberInfo) {}
public bool ShouldInterceptMethod(Type type, MethodInfo methodInfo)
{
// decide whether you need to intercept your method here
return true;
}
}
void Main()
{
var generator = new ProxyGenerator();
var options = new ProxyGenerationOptions(new CustomProxyGenerationHook());
var fileCopierProxy = generator.CreateClassProxy(typeof(FileCopier),
options
new IInterceptor[] { // specify list of interceptors
new ImpersonationInterceptor(),
new LoggingInterceptor()
}
) as FileCopier;
fileCopierProxy.CopyFile("src", "dest");
}
Even if you've got a ton of classes and modifying them all by hand is not feasible, you can still work around it by opting for yet another technique called assembly weaving. Project Fody is a good starting point, and this particular problem is best solved with Virtuosity plugin - it basically rewrites your assembly on build to mark all methods virtual so you don't have to do it yourself.
public static T DecoratorActions<T>(string desc, Func<T> func)
{
return Log(desc, () => ImpersonateAndAct(func));
}
public static void DecoratorActions(string desc, Action action)
{
Log(desc, () => ImpersonateAndAct(action));
}
public string Read(string filepath)
{
return DecoratorActions($"Reading file at '{filepath}'",
() => fileService.Read(filepath));
}
Based on these very helpful answers I've been able to determine that, while I may not be able to automatically wrap all methods of a class. I can at least reduce boilplate code and separate concerns by using the Decorator Pattern instead of the standard inheritance.
As such I have a Log method which calls "Entering {methodName}" and "Exiting {methodName}" as well as try/catching for exceptions which it also logs before throwing.
Additionally an inline way of impersonating for a specific action in the ImpersonateAndAct method.
Both of these return type of T so they wrap calls to my decorated fileService without interfering with the products of those methods.
I marked #Xander as the correct answer as he was the chief inspiration for this approach but I wanted to leave an answer to share what I came up with.
Consider the following code:
public interface IFileBackup
{
Task Backup(byte[] file);
}
public class BackUpMechanismA : IFileBackup
{
//Implementation
public async Task Backup(byte[] file)
{
//Attempts to backup using mechanism A
}
}
public class BackUpMechanismB : IFileBackup
{
//Implementation
public async Task Backup(byte[] file)
{
//Attempts to backup using mechanism B
}
}
Then the calling class looks like this:
public class Caller
{
private readonly IFileBackup _backupA;
private readonly IFileBackup _backupB;
public Caller(IFileBackup backupA, IFileBackup backupB)
{
_backupA = backupA;
_backupB = backupB;
}
public async Task BackupFile(byte[] file)
{
try
{
await _backupA.Backup(file);
}
catch(SomeException)
{
await _backupB.Backup(file);
}
}
}
So what I'm trying to do here is to use polymorphism. So both BackupMechanismA and BackupMechanismB implements the Backup method in their own way. In the caller I want to attempt the first mechanism and if that doesn't work we catch an exception and try the second approach.
I'm having trouble resolving the correct implementations using Autofac. I have tried with:
builder.RegisterType<BackupMechanismA>().As<IFileBackup>().AsSelf();
builder.RegisterType<BackupMechanismB>().As<IFileBackUp>().AsSelf();
But this won't work because I still need to tell the caller which of the types to resolve. How do I do that in the caller?
Also, I'm in doubt whether this design is really the right design to go with. Before this design I just had one class with two different methods, one for mechanism A and one for mechanism B and then the caller would just call the different methods in the try catch. So I wanted to refactor this because the class got quite big and I wanted to separate the two different mechanisms into their own classes.
So, can I resolve this using Autofac? And is it the right design to go with for this scenario?
Agree with Jogge that iterating IFileBackups would be a better option, but creating an interface for each type is a no go. Instead, you could add a class which provides IEnumerable<IFileBackup> (an aggregate). For example:
public class BackupBundle : IEnumerable<IFileBackup>
{
private readonly List<IFileBackup> _backups = new List<IFileBackup>();
// default constructor creates default implementations
public BackupBundle()
: this(new List<IFileBackup> {new BackUpMechanismA(), new BackUpMechanismB()}) {}
// allow users to add custom backups
public BackupBundle(IEnumerable<IFileBackup> backups)
{
foreach (var backup in backups)
Add(backup);
}
public void Add(IFileBackup backup)
{
if (backup == null) throw new ArgumentNullException(nameof(backup));
_backups.Add(backup);
}
public IEnumerator<IFileBackup> GetEnumerator()
{
foreach (var backup in _backups)
yield return backup;
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
public class Caller
{
private readonly IEnumerable<IFileBackup> _backups;
public Caller(IEnumerable<IFileBackup> backups)
{
_backups = backups ?? throw new ArgumentNullException(nameof(backups));
}
public async Task BackupFile(byte[] file)
{
foreach (var b in _backups)
{
try
{
await b.Backup(file);
break;
}
catch (Exception e) { }
}
}
}
Registration can be done as follows:
builder.RegisterInstance(new BackupBundle()).As<IEnumerable<IFileBackup>>();
builder.RegisterType<Caller>();
which allows you to resolve by class name:
var caller = scope.Resolve<Caller>();
As you see, the BackupBundle has a dependency of BackUpMechanismA and BackUpMechanismB. You could get rid of it by introducing another layer of abstraction but I'd prefer not to do that. My main concern would be to make Caller more robust. You might want to introduce retry logic, timeouts, etc.
Try registering with a name and then resolve using the name:
builder.RegisterType<BackupMechanismA>().Named<IFileBackup>("BackUpMechanismA");
builder.RegisterType<BackupMechanismB>().Named<IFileBackUp>("BackUpMechanismB");
_backupA = container.ResolveNamed<IFileBackUp>
("BackUpMechanismA");
_backupB = container.ResolveNamed<IFileBackUp>
("BackUpMechanismB");
Resolve the instances during runtime, rather than injecting through the constructor. This will let you resolve to the respective type, as needed.
Let me know if this works.
To make your design work, you can try the next approach:
static void Main(string[] args)
{
var builder = new ContainerBuilder();
builder.RegisterType<BackUpMechanismA>().Keyed<IFileBackup>("A");
builder.RegisterType<BackUpMechanismB>().Keyed<IFileBackup>("B");
builder.RegisterType<Caller>()
.WithParameter((p, ctx) => p.Position == 0, (p, ctx) => ctx.ResolveKeyed<IFileBackup>("A"))
.WithParameter((p, ctx) => p.Position == 1, (p, ctx) => ctx.ResolveKeyed<IFileBackup>("B"));
IContainer container = builder.Build();
var caller = container.Resolve<Caller>();
Console.ReadKey();
}
However in my opinion you probably don't need such a polymorphism here. It will be much more obvious and descriptive to implement something like this:
public async Task BackupFile(byte[] file)
{
try
{
await BackUpToAmazonS3(file);
}
catch (AmazonS3LoadingException)
{
await BackUpToLocalDisk(file);
}
}
In this example it is obvious what is going on. And there in BackUpToAmazonS3 you can use some injected AmazonS3FileBackUp and in BackUpToLocalDisk use LocalDiskFileBackUp or whatever. The point is that you don't need a polymorphism, when you don't plan to change the implementation. In your context it should be clear? that you try to put backup to some remote storage, and then, if it fails, put in on local disk. You don't need to hide the meaning here. This is your logic and should be clear, when you read the code, I suppose. Hope it helps.
In my experience, you're better off by creating an interface for each type:
public interface IFileBackup
{
Task Backup(byte[] file);
}
public interface IBackUpMechanismA : IFileBackup
{
}
public class BackUpMechanismA : IBackUpMechanismA
{
//...
}
public interface IBackUpMechanismB : IFileBackup
{
}
public class BackUpMechanismB : IBackUpMechanismB
{
//...
}
If you don't want that, what you could do is getting injected a list of IFileBackup and just iterate them. If you register BackUpMechanismA first it will be the first in the list. I'm not sure if this is guaranteed, you have to look it up.
public class Caller
{
private readonly ICollection<IFileBackup> _fileBackups;
public Caller(ICollection<IFileBackup> fileBackups)
{
_fileBackups = fileBackups;
}
public async Task BackupFile(byte[] file)
{
foreach (var fileBackup in _fileBackups)
{
try
{
await fileBackup.Backup(file);
break;
}
catch { }
}
}
}
I am trying to learn Unity Interceptors and I am having a hard go of it.
Say I have an interface like this:
public interface IMyInterface
{
void SomeMethod();
}
And I have an unknown number of classes that implement that interface like this:
public class SpecificClass1 : IMyInterface
{
public void SomeMethod()
{
Console.WriteLine("Method Called");
}
}
I am looking for a way to say, "for all instance of IMyInterface (I don't want to enumerate them), when SomeMethod is called run my interceptor.
It is the Non-Enumeration of the classe that is giving me trouble. (There are plenty of examples if you can enumerate all your classes.)
I have read of Type Interception, but I can't seem to find out if it will do what I am looking for.
Any Unity experts out there know how to do what I am looking for?
You could create InterceptionBehavior then register it on specific class. Note you could filter executing methods in Invoke thru IMethodInvocation input
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.InterceptionExtension;
using NUnit.Framework;
namespace UnitTests
{
[TestFixture]
public class ForTest
{
[Test]
public void Test()
{
IUnityContainer container = new UnityContainer().AddNewExtension<Interception>();
container.RegisterType<IMyInterface, SpecificClass1>(
new Interceptor<InterfaceInterceptor>(),
new InterceptionBehavior<MyInterceptionBehavior>());
var myInterface = container.Resolve<IMyInterface>();
myInterface.SomeMethod();
}
}
public interface IMyInterface
{
void SomeMethod();
}
public class SpecificClass1 : IMyInterface
{
#region IMyInterface
public void SomeMethod()
{
Console.WriteLine("Method Called");
}
#endregion
}
public class MyInterceptionBehavior : IInterceptionBehavior
{
public bool WillExecute
{
get { return true; }
}
#region IInterceptionBehavior
public IEnumerable<Type> GetRequiredInterfaces()
{
return Enumerable.Empty<Type>();
}
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
IMethodReturn result = getNext()(input, getNext);
Console.WriteLine("Interception Called");
return result;
}
#endregion
}
}
Console output
Method Called
Interception Called
More about Interception with Unity
#GSerjo, has outlined the Unity interception approach which works well. If you wanted to automate the configuration of interception you can use a UnityContainerExtension to automatically wire up all the interface interception as well as the behaviors. If you wanted to get into more specific interception (method names, signatures, return values etc.) then you would probably need to look at Policy Injection (using matching rules with CallHandlers).
So in this case the container extension would look like:
public class UnityInterfaceInterceptionRegisterer : UnityContainerExtension
{
private List<Type> interfaces = new List<Type>();
private List<IInterceptionBehavior> behaviors =
new List<IInterceptionBehavior>();
public UnityInterfaceInterceptionRegisterer(Type interfaceType,
IInterceptionBehavior interceptionBehavior)
{
interfaces.Add(interfaceType);
behaviors.Add(interceptionBehavior);
}
public UnityInterfaceInterceptionRegisterer(Type[] interfaces,
IInterceptionBehavior[] interceptionBehaviors)
{
this.interfaces.AddRange(interfaces);
this.behaviors.AddRange(interceptionBehaviors);
ValidateInterfaces(this.interfaces);
}
protected override void Initialize()
{
base.Container.AddNewExtension<Interception>();
base.Context.Registering +=
new EventHandler<RegisterEventArgs>(this.OnRegister);
}
private void ValidateInterfaces(List<Type> interfaces)
{
interfaces.ForEach((i) =>
{
if (!i.IsInterface)
throw new ArgumentException("Only interface types may be configured for interface interceptors");
}
);
}
private bool ShouldIntercept(RegisterEventArgs e)
{
return e != null && e.TypeFrom != null &&
e.TypeFrom.IsInterface && interfaces.Contains(e.TypeFrom);
}
private void OnRegister(object sender, RegisterEventArgs e)
{
if (ShouldIntercept(e))
{
IUnityContainer container = sender as IUnityContainer;
var i = new Interceptor<InterfaceInterceptor>();
i.AddPolicies(e.TypeFrom, e.TypeTo, e.Name, Context.Policies);
behaviors.ForEach( (b) =>
{
var ib = new InterceptionBehavior(b);
ib.AddPolicies(e.TypeFrom, e.TypeTo, e.Name, Context.Policies);
}
);
}
}
}
Then you could use it like so:
IUnityContainer container = new UnityContainer()
.AddExtension(new UnityInterfaceInterceptionRegisterer(
new Type[] { typeof(IMyInterface),
typeof(IMyOtherInterface) },
new IInterceptionBehavior[] { new MyInterceptionBehavior(),
new AnotherInterceptionBehavior() }
));
container.RegisterType<IMyInterface, SpecificClass1>();
var myInterface = container.Resolve<IMyInterface>();
myInterface.SomeMethod();
Now when the interface is registered the appropriate interception policies will also be added to the container. So in this case if the interface registered is of type IMyInterface or IMyOtherInterface then policies will be setup for interface interception and the Interception Behaviors MyInterceptionBehavior and AnotherInterceptionBehavior will also be added.
Note that Unity 3 (released after this question/answer) added a Registration by Convention feature that can do what this extension does (without having to write any custom code). An example from the Developer's Guide to Dependency Injection Using Unity:
var container = new UnityContainer();
container.AddNewExtension<Interception>();
container.RegisterTypes(
AllClasses.FromLoadedAssemblies().Where(
t => t.Namespace == "OtherUnitySamples"),
WithMappings.MatchingInterface,
getInjectionMembers: t => new InjectionMember[]
{
new Interceptor<VirtualMethodInterceptor>(),
new InterceptionBehavior<LoggingInterceptionBehavior>()
});
Setting up interception requires multiple actions incl. configuration of intercepted types, policies and handlers.
First see Using Interception in Applications for general details about the types of situations where interception is supported (with or without a DI container for example). Then see Type Interception for more details about the supported type interceptors. Especially take note of what interceptors can be used with the type of your class (otherwise the handlers will never trigger).
When you have decided what interceptor to use, configure it and create a sufficient call handler as per the links above. If you still have trouble at this point, post a more detailed question. If you have already done this, please post the configs and code as "non-enumeration of the classe" simply does not give any hints what you are actually asking. Do you by any chance mean with "enumeration" that you assign a attribute-driven policy and are unable to achieve what you want without it?
I meet one problem that i can't solve now.
I have the following:
UnityHelper.DefaultContainer.RegisterInstance(typeof(IMyInterface), "test", instance);
where UnityHelper.DefaultContainer is my helper for getting unity container with loaded configuration.
here I registered instance as an instance of IMyInterface.
So anywhere( some time after using) I want to remove this mapping. Remove it at all. How I can do it?
I have tried:
UnityHelper.DefaultContainer.Teardown(instance)
but is was unsuccessful and the following code returns instance anyway:
UnityHelper.DefaultContainer.ResolveAll<IMyInterface>()
I had the same problem and just removed the registrations of the ContainerControlledLifetimeManager from my Container:
foreach (var registration in container.Registrations
.Where(p => p.RegisteredType == typeof(object)
&& p.Name == name
&& p.LifetimeManager.Type == typeof(ContainerControlledLifetimeManager)))
{
registration.LifetimeManager.RemoveValue();
}
This is an old question, but some answers are misleading, so I will provide my own.
You can´t do that with Unity. End of the story.
Calling RemoveValue on registrations lifetime managers does not achieve unregistration (more information about lifetime managers), and that method is not intended to unregister anything. So the final behaviour is unexpected and not convenient. Of course, RemoveValue makes even less sense if you register an implementation or a factory method, although the question is about unregistering instances.
Consider the next piece of code
public interface SomeInterface
{
int Foo { get; set; }
}
public class SomeImplementation: SomeInterface
{
public int Foo { get; set; }
}
static void Main(string[] args)
{
UnityContainer iocContainer = new UnityContainer();
string registerName = "instance";
//before any registration
Resolve<SomeInterface>(iocContainer, registerName);
iocContainer.RegisterInstance<SomeInterface>(registerName, new SomeImplementation());
//after registration
Resolve<SomeInterface>(iocContainer, registerName);
ClearValue<SomeInterface>(iocContainer, registerName);
//after clear value
Resolve<SomeInterface>(iocContainer, registerName);
}
private static void Resolve<T>(UnityContainer iocContainer,string name)
{
if (iocContainer.IsRegistered<T>(name))
iocContainer.Resolve<T>(name);
iocContainer.ResolveAll<T>();
}
private static void ClearValue<T>(UnityContainer iocContainer, string name)
{
foreach (var registration in iocContainer.Registrations.Where(p => p.RegisteredType == typeof(T)
&& p.Name==name))
{
registration.LifetimeManager.RemoveValue();
}
}
If you debug it, you will see that after the call to ClearValue, the container still says it is registered, but if you try to resolve that instance it will throw an exception. What is even worse, calls to ResolveAll<T> will fail too.
To Sum up, no matter if you do ClearValue, wrap around your register instance with another IoC or a custom class, or provide your own LifeTimeManager, ResolveAll<T> and IsRegistered<T> won´t behave as expected, and the registration will still be there. So don't try it because it won´t work and it will cause problems down the road.
I think that is what you are looking for.
var lifetimeManager = new TransientLifetimeManager();
UnityHelper.DefaultContainer.RegisterInstance(typeof(IMyInterface), "test", instance, lifetimeManager);
lifetimeManager.RemoveValue();
Here is how I handled unregistering instances from a unity container
I needed to implement Add/Remove functionality like this:
public interface IObjectBuilder
{
void AddInstance<T>(T instance);
void RemoveInstance<T>(T instance);
}
I created a custom lifetime manager to do the implementation
public class ExplicitLifetimeManager :
LifetimeManager
{
object Value;
public override object GetValue()
{
return Value;
}
public override void SetValue(object newValue)
{
Value = newValue;
}
public override void RemoveValue()
{
Value = null;
}
}
Here is the final implementation:
Dictionary<object, ExplicitLifetimeManager> Instances = new Dictionary<object, ExplicitLifetimeManager>();
public void AddInstance<T>(T instance)
{
ExplicitLifetimeManager e = new ExplicitLifetimeManager();
Instances[instance] = e;
Container.RegisterInstance(instance, e);
}
public void RemoveInstance<T>(T instance)
{
Instances[instance].RemoveValue();
Instances.Remove(instance);
}
calling removevalue on the custom lifetime manager causes the instance to be unregistered
I have the same challenge and after experimenting I solved it by using the standard ContainerControlledLifetimeManager and calling RemoveValue when I want to remove the container instance. Note that if you are not using interfaces and your object has constructor which the container can find and use it will recreate the instance after you have destroyed it with lifetimeManager.RemoveValue().
[TestClass]
public class UnityContainerTest
{
[TestMethod]
public void RemoveFromContainer()
{
UnityContainer container = new UnityContainer();
MyUnityMember member = new MyUnityMember(5);
LifetimeManager lifetimeManager = new ContainerControlledLifetimeManager();
container.RegisterInstance(member, lifetimeManager);
var resolved = container.Resolve<MyUnityMember>();
Assert.IsNotNull(resolved);
lifetimeManager.RemoveValue();
try
{
resolved = container.Resolve<MyUnityMember>();
Assert.Fail(resolved + " is still in the container");
}
catch (ResolutionFailedException)
{
}
}
public class MyUnityMember
{
public MyUnityMember(int x)
{
I = x;
}
public int I { get; private set; }
}
}
I had a similar requirement whereby I wanted to temporarily store objects in the unity container and found this was not possible (or at least easily possible).
If your objective is to have a temporary storage place easily available to unity, then create a temporary storage service.
public class TemporaryStorageService : ITemporaryStorageService
{
public void Deposit<T>(Object o, string key)
{
System.Windows.Application.Current.Properties[key] = o;
}
public T Withdraw<T>(string key)
{ T o = (T)System.Windows.Application.Current.Properties[key];
System.Windows.Application.Current.Properties.Remove(key);
return o;
}
}
Register your service with Unity. Then when you wish to store an object you call the Deposit Method and when you wish to remove the object you call the Withdraw method.
A fuller explanation can be found here