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?
Related
Was unsure how to make a sensible title for this post.
Say I have a class
[Export(typeof(IMessageSender))]
public class MessageSender : IMessageSender
{
private IMessagingInterface _messagingInterface;
private IEventAggregator _eventAggregator;
[ImportingConstructor]
public MessageSender(IMessagingInterface messagingInterface, IEventAggregator eventAggregator)
{
_messagingInterface = messagingInterface;
_eventAggregator = eventAggregator;
}
public void SendMessage(string message)
{
_messagingInterface.Write(message);
}
public InterfaceStatus GetStatus()
{
return _messagingInterface.Status;
}
...
etc. Many methods in this class.
}
and I have several different IMessagingInterface, such as
[Export(typeof(IMessagingInterface))]
public SerialPortInterface : IMessagingInterface
{
..
}
[Export(typeof(IMessagingInterface))]
public UdpInterface : IMessagingInterface
{
..
}
etc
In my application, I currently instantiate the different parts like this at the startup of my application:
eventAggregator = new EventAggregator();
batch.AddExportedValue<IMessageSender>("SerialPortSender", new MessageSender(new SerialPortInterface(), eventAggregator);
batch.AddExportedValue<IMessageSender>("UdpSender", new MessageSender(new UdpInterface (), eventAggregator);
...
etc for the rest
Then I can specify which one I want injected elsewhere by using the contract name.
However, I feel like doing this composition myself in the bootstrapper and creating instances with new is wrong and unnecessary, but I haven't found a way to do it differently.
Have a look at this post:
Getting all types that implement an interface
And then use Activator.CreateInstance(...) to construct the instances (see: https://msdn.microsoft.com/en-us/library/system.activator.createinstance.aspx)
Something like this should do it:
eventAggregator = new EventAggregator();
var type = typeof(IMyInterface);
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => type.IsAssignableFrom(p));
foreach (var t in types)
{
var instance = (IMyInteface)Activator.CreateInstance(t);
batch.AddExportedValue<IMessageSender>(t.Name, new MessageSender(instance, eventAggregator);
}
As Tchi Yuan pointed out, using a IOC framework is also an option such as:
Unity
Ninject
These will handle the scanning of assemblies and instance creation for you according to the configurations you provide.
I've had this problem in the past and what I did is that I used Microsoft Unity in conjuncture with MEF and then simply pass your unity container to your MEF extension/plugin constructor. Registering and resolving named dependencies with Unity is trivial.
I put a question here: Raising Domain Events For Multiple Subscribers and the answer led me to the following pattern where I can have an IEventPublisher like so:
public interface IEventPublisher<T>
{
void Publish(T data);
}
and an IEventSubscriber like so:
public interface IEventSubscriber<T>
{
void Handle(T data);
}
The problem with this is that I need to pass an instance of each publisher to a constructor like so:
public Service(IEventPublisher<ThingyChangedEvent> publisherThingyChanged)
{
// Set publisher to local variable
}
// then call this in a method
_publisherThingyChanged.Publish(new ThingyChangedEvent { ThingyId = model.Id});
What I would ideally like to be able to do is have a generic publisher which contains any IEventPublishers so I can call somthing like:
_genericPublisher.Publish(new ThingyChangedEvent { ThingyId = model.Id});
I can't figure out how to do this though as I can't pass a collection of IEventPublisher without defining T as in this example as ThingyChangedEvent whereas what I want is to determine the publisher based on the type that is passed to the generic publisher.
Any suggestions much appreciated.
EDIT:
OK using the answer below and some info from here: http://www.udidahan.com/2009/06/14/domain-events-salvation/ I came up with the following but it's not quite there:
public interface IEventManager
{
void Publish<T>(T args) where T : IEvent;
}
public class EventManager : IEventManager
{
Autofac.ILifetimeScope _container;
public EventManager(Autofac.ILifetimeScope container)
{
_container = container;
}
//Registers a callback for the given domain event
public void Publish<T>(T args) where T : IEvent
{
var subscribersProvider = _container.Resolve<IEventSubscribersProvider<T>>();
foreach (var item in subscribersProvider.GetSubscribersForEvent())
{
item.Handle(args);
}
}
}
I can now take an instance of IEventManager eventManager in a constructor resolved by autofac and call it as follows:
_eventManager.Publish<ThingyChangedEvent>(new ThingyChangedEvent() { ThingyId = Guid.NewGuid() });
Here is what I don't like about this solution:
I don't want to take an instance of ILifetimeScope in the constructor, I want to be able to take a collection of IEventSubscribersProvider but autofac won't resolve this if I ask for say:
IEnumerable<IEventSubscribersProvider<IEvent>>
I can only resolve it if I pass the type to the Publish and call:
Resolve<IEventSubscribersProvider<T>>.
The second issue is not a huge deal but would be nice to be able to call publish without having to pass the type as well like so:
_eventManager.Publish(new ThingyChangedEvent() { ThingyId = Guid.NewGuid() });
I think if anyone has any suggestions of how to solve these two issues, particularly issue 1 as I don't like putting a dependency on Autofac in different projects. The only thing I can come up with is a manager class of some kind which explicitly takes what I need as follows:
public SomeConstructor(
IEventSubscribersProvider<ThingyChangedEvent> thingChangedSubscribeProviders,
IEventSubscribersProvider<SomeOtherEvent> someOtherSubscribeProviders,
etc....)
{
// Maybe take the EventManager as well and add them to it somehow but would be
// far easier to take a collection of these objects somehow?
}
Many thanks for any suggestions.
EDIT 2
After a lot of research and looking at this Autofac Generic Service resolution at runtime I am not sure I can achieve what I want to. The best solution I can come up with is this:
public interface IEventSubscribersProviderFactory : Amico.IDependency
{
IEventSubscribersProvider<T> Resolve<T>() where T : IEvent;
}
public class EventSubscribersProviderFactory : IEventSubscribersProviderFactory
{
Autofac.ILifetimeScope _container;
public EventSubscribersProviderFactory(Autofac.ILifetimeScope container)
{
_container = container;
}
public IEventSubscribersProvider<T> Resolve<T>() where T : IEvent
{
return _container.Resolve<IEventSubscribersProvider<T>>();
}
}
And then have the EventManager take IEventSubscribersProviderFactory in the constructor to remove the dependency on Autofac from that project.
I'll go with this for now but hopefully will find a better solution int the long term.
It can get a bit complex when you have to deal with multiple types of events. As you've probably noticed you can't just use a derived generic type and expect to use it like a base generic--.NET variance doesn't support that where you'd want to use it.
You need a "base" type that would be the minimum (or most narrow) type that you'd accept as an "event". I generally use a marker interface like public interface IEvent{}. You could, of course, derive from Object; but I find it useful to have marker interfaces to make the fact that you're subscribing or publishing an "event" explicit (and means you can't just publish any type of object, just "events").
From the handling of multiple type aspect, you need to write a class to do the narrowing (taking a derived type and "publish" the same object cast to the derived type). Even with that you need to route your events through an appropriate instance of a narrower (to "get around" the variance limitations). Then, of course, you could have multiple subscribers to the same event type; so you need something to route an event to the multiple subscribers. This is generally called a Multiplexor, which would be a specialization of IEventPublisher. You'll need one multiplexor per event type--which would use the narrower. Which multiplexor to use for a given event depends on type, so that collection of multiplexors would be managed by a dictionary so you can look them up by type. Then, to publish an event to multiple subscribers, by type, you simple look up the multiplexor and call its IEventPublisher.Publish method. And something that manages the multiplexors is a type of IEventPublisher and is generally called a Dispatcher (some might call it a router).
For example:
public class NarrowingSubscriber<TBase, TDerived> : IEventSubscriber<TBase>
where TDerived : TBase
where TBase : IEvent
{
private IEventSubscriber<TDerived> inner;
public NarrowingSubscriber(IEventSubscriber<TDerived> inner)
{
if (inner == null) throw new ArgumentNullException("inner");
this.inner = inner;
}
public void AttachSubscriber(IEventSubscriber<TDerived> subscriber)
{
inner = subscriber;
}
public void Handle(TBase data)
{
inner.Handle((TDerived)data);
}
}
public class Multiplexor<T> : IEventSubscriber<T> where T : IEvent
{
private readonly List<IEventSubscriber<T>> subscribers =
new List<IEventSubscriber<T>>();
public void AttachSubscriber(IEventSubscriber<T> subscriber)
{
subscribers.Add(subscriber);
}
public void RemoveSubscriber(IEventSubscriber<T> subscriber)
{
subscribers.Remove(subscriber);
}
public void Handle(T data)
{
subscribers.ForEach(x => x.Handle(data));
}
}
public class Dispatcher<TBase> : IEventPublisher<TBase> where TBase : IEvent
{
private readonly Dictionary<Type, Multiplexor<TBase>> subscriptions =
new Dictionary<Type, Multiplexor<TBase>>();
public void Publish(TBase data)
{
Multiplexor<TBase> multiplexor;
if (subscriptions.TryGetValue(data.GetType(), out multiplexor))
{
multiplexor.Handle(data);
}
}
public void Subscribe<TEvent>(IEventSubscriber<TEvent> handler)
where TEvent : TBase
{
Multiplexor<TBase> multiplexor;
if (!subscriptions.TryGetValue(typeof(TEvent), out multiplexor))
{
multiplexor = new Multiplexor<TBase>();
subscriptions.Add(typeof(TEvent), multiplexor);
}
multiplexor.AttachSubscriber(new NarrowingSubscriber<TBase, TEvent>(handler));
}
}
So, you're basically publishing 4 times. Once to the dispatcher, once to the multiplexor, once to the narrower, and once to the non-infrastructure subscriber. If you had two subscribers (EventOneEventSubscriber and EventTwoEventSubscriber) that subscribed to two types of events (EventOne and EventTwo) then you might create a dispatcher and publish events like this:
var d = new Dispatcher<IEvent>();
var eventTwoSubscriber = new EventTwoEventSubscriber();
d.Subscribe(eventTwoSubscriber);
var eventOneSubscriber = new EventOneEventSubscriber();
d.Subscribe(eventOneSubscriber);
d.Publish(new EventOne());
d.Publish(new EventTwo());
Of course, the events would derive from IEvent:
public class EventOne : IEvent
{
}
public class EventTwo : IEvent
{
}
This particular limitation does not take into account dispatching events multiple times. For example, I could have on subscriber to EventOne and one subscriber for IEvent. This implementation just publishes to the EventOne subscriber if an EventOne object is published through the dispatcher--it wouldn't publish to the IEvent subscriber. I'll leave that as an exercise for the reader :)
Update:
If what you're hoping to do is to auto-wire the subscribers without having to construct them (I don't see much value in this, consider a Composition Root) then you can add a fairly simple method to the Dispatcher (or elsewhere, if needed) to subscribe all compatible subscribers:
public void InitializeSubscribers()
{
foreach (object subscriber in
from assembly in AppDomain.CurrentDomain.GetAssemblies()
from type in assembly.GetTypes()
where !type.IsAbstract && type.IsClass && !type.ContainsGenericParameters &&
type.GetInterfaces().Any(t => t.IsGenericType &&
t.GetGenericTypeDefinition() == typeof (IEventSubscriber<>))
select type.GetConstructor(new Type[0])
into constructorInfo
where constructorInfo != null
select constructorInfo.Invoke(new object[0]))
{
Subscribe((dynamic) subscriber);
}
}
in which you'd use as follows:
var d = new Dispatcher<IEvent>();
d.InitializeSubscribers();
...using a container to resolve the Dispatcher<T> object, if you want.
First, the simple question.
Is it possible to receive an event when MEF (System.ComponentModel.Composition) creates an instance of a part?
When this occurs I want to reflect over the created object and wire up various attributes. In Spring.Net this is possible with the IObjectPostProcessor interface.
The background is that I trying to implement Publisher/Subscriber pattern in MEF. Basically the subscriber class does this:
class MyContoller
{
[Command("Print")]
public void Print() { ... }
[Command("PrintPreview")]
public void PrintPreview() { ... }
}
And I want to detect when MyController is instantiated and wire up any methods that have the CommandAttribute.
A publisher, such as a menu item, would do Command.Get("Print").Fire() to publish the aforementioned event.
Second Question
Maybe there is an alternative pattern in MEF that I am missing!!!
I've seen some postings about MEF, Prism and the Event Aggregate, but it appears fairly complex.
FYI
Just for reference, here's the original for Spring.Net implementation:
class CommandAttributeProcessor : IObjectPostProcessor
{
static ILog log = LogManager.GetLogger(typeof(CommandAttributeProcessor));
public object PostProcessAfterInitialization(object instance, string objectName)
{
foreach (MethodInfo methodInfo in instance.GetType().GetMethods())
{
foreach (CommandAttribute attr in methodInfo.GetCustomAttributes(typeof(CommandAttribute), true))
{
if (log.IsDebugEnabled)
log.Debug(String.Format("Binding method '{0}.{1}' to command '{2}'.", instance.GetType().Name, methodInfo.Name, attr.CommandName));
Command command = Command.Get(attr.CommandName);
command.Execute += (EventHandler) Delegate.CreateDelegate(typeof(EventHandler), instance, methodInfo);
}
}
return instance;
}
public object PostProcessBeforeInitialization(object instance, string name)
{
return instance;
}
}
This may not help, but the part itself can receive notification when it is fully composed:
Automatically call method after part has been composed in MEF
Also, you probably already know this (and it might not really be related to what you are trying to do), but you can decorate your Exports and Imports such the concrete implementations are named. So, you could have an exported class something like this:
[Export("Print", typeof(IPlugin))]
[PartCreationPolicy(CreationPolicy.Shared)]
class Print : IPlugin
{
.
.
.
public Fire()
{
//Do something;
}
}
class PrintMenuItem
{
IPlugin _plugin;
[ImportingConstructor]
PrintMenuItem([Import("Print", typeof(IPlugin)] plugin)
{
_plugin = plugin;
}
void Execute()
{
_plugin.Fire();
}
}
You can use InterceptingCatalog from MEF Contrib (MEF Contrib on codeplex or you can install it by nuGet) and implement IExportedValueInterceptor interface to wire up methods that have CommandAttribute:
//using System.ComponentModel.Composition;
//using System.ComponentModel.Composition.Hosting;
//using MefContrib.Hosting.Interception;
//using MefContrib.Hosting.Interception.Configuration;
public class CommandAttributeProcessor : IExportedValueInterceptor
{
public object Intercept(object value)
{
foreach (MethodInfo methodInfo in value.GetType().GetMethods())
{
foreach (CommandAttribute attr in methodInfo.GetCustomAttributes(typeof(CommandAttribute), true))
{
// do something with command attribute
}
}
return value;
}
}
and at creating MEF catalog, you need to add interception configuration with your interceptor (CommandAttributeProcessor) and wrap your catalog in InterceptingCatalog like this:
InterceptionConfiguration interceptionConfiguration = new InterceptionConfiguration();
interceptionConfiguration.AddInterceptor(new CommandAttributeProcessor());
InterceptingCatalog interceptingCatalog = new InterceptingCatalog(assemblyCatalog, interceptionConfiguration);
CompositionContainer container = new CompositionContainer(interceptingCatalog);
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
I am using the Unity IoC container, and I need to intercept any calls to Resolve for a certain base interface, and run my own custom code to construct those types.
In other words, in the sample code below, when I call container.Resolve<IFooN>(), if it hasn't got an instance of the concrete implementing type, it calls MyFactoryFunction to construct one, otherwise I want it to return the cached copy.
The standard Unity container is not able to construct these objects (update: because they are .NET remoting objects, so the concrete classes do not exist in any assembly on the local computer), and I don't want to create them up front and store them with RegisterInstance.
interface IFoo : IBase { ... }
interface IFoo2 : IBase { ... }
...
container.Resolve<IFoo2>();
...
IBase MyFactoryFunction(Type t)
{
...
}
I'm assuming I can create a Unity extension to do this, but I was wondering if there is already a solution out there I can borrow.
For completeness, I should add another answer that works under Unity 2, since my other answer no longer works. It is slightly more involved since you need to make a custom builder policy. Thanks to ctavares from the Unity project who provided lots of help on this thread in implementing this:
public class FactoryUnityExtension : UnityContainerExtension
{
private ICustomFactory factory;
private CustomFactoryBuildStrategy strategy;
public FactoryUnityExtension(ICustomFactory factory)
{
this.factory = factory;
}
protected override void Initialize()
{
this.strategy = new CustomFactoryBuildStrategy(factory, Context);
Context.Strategies.Add(strategy, UnityBuildStage.PreCreation);
Context.Policies.Set<ParentMarkerPolicy>(new ParentMarkerPolicy(Context.Lifetime), new NamedTypeBuildKey<ParentMarkerPolicy>());
}
}
public class ParentMarkerPolicy : IBuilderPolicy
{
private ILifetimeContainer lifetime;
public ParentMarkerPolicy(ILifetimeContainer lifetime)
{
this.lifetime = lifetime;
}
public void AddToLifetime(object o)
{
lifetime.Add(o);
}
}
public interface ICustomFactory
{
object Create(Type t);
bool CanCreate(Type t);
}
public class CustomFactoryBuildStrategy : BuilderStrategy
{
private ExtensionContext baseContext;
private ICustomFactory factory;
public CustomFactoryBuildStrategy(ICustomFactory factory, ExtensionContext baseContext)
{
this.factory = factory;
this.baseContext = baseContext;
}
public override void PreBuildUp(IBuilderContext context)
{
var key = (NamedTypeBuildKey)context.OriginalBuildKey;
if (factory.CanCreate(key.Type) && context.Existing == null)
{
context.Existing = factory.Create(key.Type);
var ltm = new ContainerControlledLifetimeManager();
ltm.SetValue(context.Existing);
// Find the container to add this to
IPolicyList parentPolicies;
var parentMarker = context.Policies.Get<ParentMarkerPolicy>(new NamedTypeBuildKey<ParentMarkerPolicy>(), out parentPolicies);
// TODO: add error check - if policy is missing, extension is misconfigured
// Add lifetime manager to container
parentPolicies.Set<ILifetimePolicy>(ltm, new NamedTypeBuildKey(key.Type));
// And add to LifetimeContainer so it gets disposed
parentMarker.AddToLifetime(ltm);
// Short circuit the rest of the chain, object's already created
context.BuildComplete = true;
}
}
}
Update This answer was for Unity 1.2. For a solution that works with Unity 2, see my other answer.
OK, I have implemented the extension myself. In the builder I cache the object as I want it to be a singleton w.r.t my container. The reason for baseContext is that I want it to be cached in the top level container rather than in any child containers from which it was requested.
public class FactoryMethodUnityExtension<T> : UnityContainerExtension
{
private Func<Type,T> factory;
public FactoryMethodUnityExtension(Func<Type,T> factory)
{
this.factory = factory;
}
protected override void Initialize()
{
var strategy = new CustomFactoryBuildStrategy<T>(factory, this.Context);
Context.Strategies.Add(strategy, UnityBuildStage.PreCreation);
}
}
public class CustomFactoryBuildStrategy<T> : BuilderStrategy
{
private Func<Type,T> factory;
private ExtensionContext baseContext;
public CustomFactoryBuildStrategy(Func<Type,T> factory, ExtensionContext baseContext)
{
this.factory = factory;
this.baseContext = baseContext;
}
public override void PreBuildUp(IBuilderContext context)
{
var key = (NamedTypeBuildKey)context.OriginalBuildKey;
if (key.Type.IsInterface && typeof(T).IsAssignableFrom(key.Type))
{
object existing = baseContext.Locator.Get(key.Type);
if (existing == null)
{
// create it
context.Existing = factory(key.Type);
// cache it
baseContext.Locator.Add(key.Type, context.Existing);
}
else
{
context.Existing = existing;
}
}
}
}
Adding the extension is quite simple:
MyFactory factory = new MyFactory();
container = new UnityContainer();
container.AddExtension(new FactoryMethodUnityExtension<IBase>(factory.Create));
Unity (v2) allows you to specify a factory. It allows a couple of different functions, including taking the type to build up/ name, etc. Simple example:
UnityContainer cont = new UnityContainer();
have a simple create test method - but this can be expanded with whatever factory you want.
this will circumvent the normal creation process which is (for the sake of brevity) call the
longest constructor
all later behaviors including propert setting will still be executed.
cont.RegisterType<TestClass>(new InjectionFactory(c => CreateTest()));
var svc = cont.Resolve<TestClass>();
The Unity container already acts as a factory that knows how to construct (and perform dependency injection for) arbitrary types, so your factory that accepts a Type t appears redundant. Can you elaborate more on why this is not possible?
If this is truly not possible (more likely just too much work), then perhaps you can register your factory with the container instead?