Simple Injector Inject IEnumerable<Func<T>> - c#

How Can I inject IEnumerable<Func<T>> using Simple Injector?
Just to add some context, I'm trying to create all EventHandlers that knows how to handle one specific Event. So here is my Container registration:
container.RegisterCollection(typeof(IHandleDomainEvent<>),
AppDomain.CurrentDomain.GetAssemblies());
And here Are two classes that implement the IHandleEvent<T> interface for the same Event:
public class Reservation : IHandleDomainEvent<OrderConfirmed>{}
public class Order: IHandleDomainEvent<OrderConfirmed>{}
So when I call the Simple Injector:
var handlers = _container.GetAllInstances<Func<IHandleDomainEvent<OrderConfirmed>>>();
I would like to Receive IEnumerable<Func<IHandleDomainEvent<OrderConfirmed>>>
Just to clarify, I know that if I call:
var handlers = _container.GetAllInstances<IHandleDomainEvent<OrderConfirmed>>();
I would get an IEnumerable<IHandleDomainEvent<OrderConfirmed>>.
For interfaces that have only one implementation, registering using:
container.Register(typeof(IHandleDomainEvent<>),
AppDomain.CurrentDomain.GetAssemblies(), Lifestyle.Scoped);
And adding the following ResolveUnregisteredType to the end of the registration:
container.ResolveUnregisteredType += (o, args) => ResolveFuncOfT(o, args, container);
// Function
private static void ResolveFuncOfT(object s, UnregisteredTypeEventArgs e, Container container)
{
var type = e.UnregisteredServiceType;
if (!type.IsGenericType || type.GetGenericTypeDefinition() != typeof(Func<>)) return;
Type serviceType = type.GetGenericArguments().First();
InstanceProducer producer = container.GetRegistration(serviceType, true);
Type funcType = typeof(Func<>).MakeGenericType(serviceType);
var factoryDelegate = Expression.Lambda(funcType, producer.BuildExpression()).Compile();
e.Register(Expression.Constant(factoryDelegate));
}
Will allow calling:
var handler = _container.GetInstance<Func<IHandleDomainEvent<TEvent>>>();

This is the beauty of Simple Injector: You'll never have to resolve an IEnumerable<Func<T>> because any IEnumerable<T> resolved by Simple Injector already functions as a stream.
This means that when you resolve an IEnumerable<T>, none of the elements of the stream will be resolved. They get only resolved when iterating the enumerable, and are resolved one-by-one.
When iterating the stream, elements will be resolved according to their lifestyle. This means that when the elements in the collection are Transient iterating the stream twice will cause the creation of new transient instances.
Example:
// Only resolves the enumerable, not the contained handlers.
// This enumerable itself is a singleton, you can reference it forever.
var collection = container.GetInstances<IEventHandler<OrderConfirmed>>();
// Calls back into the container to get the first element, but nothing more
var first = collection.First();
// Since the stream that Simple Injector returns is a IList<T>, getting the last
// element is an O(1) operation, meaning that only the last element is resolved;
// not the complete collection.
var last = collection.Last();
// Calling .ToArray(), however, will obviously resolve all registrations that are
// part of the collection.
var all = collection.ToArray();
// Iterating a stream will always call back into the container, which ensures
// that the stream adheres to the elements lifestyles. Transients will be
// created on each iteration, while singletons will only be created once.
container.Register<Apple>(Lifestyle.Transient);
container.Register<Banana>(Lifestyle.Singleton);
container.RegisterCollection<IFruit>(typeof(Apple), typeof(Banana));
var fruits = container.GetAllInstances<IFruit>();
Assert.AreNotSame(fruits.First(), fruits.First());
Assert.AreSame(fruits.Last(), fruits.Last());
// Even other collection types such as IReadOnlyCollection<T> behave as streams
var col = container.GetInstance<IReadOnlyCollection<IEventHandler<OrderConfirmed>>();
// This gives you the possibility to get a particular item by its index.
var indexedItem = col[3];
You can find more information on working with collections in Simple Injector here:
Simple Injector Documentation - Using - Collection types
Simple Injector Documentation - Advanced - Auto-Registration
Simple Injector Documentation - Design Decisions -
The API clearly differentiates the registration of collections
Simple Injector Documentation - Collections and lifetime management

Related

SimpleInjector Lazy in a Reflection

We are using SimpleInjector as a Dependency Injector, and we are registering all interface types using assembly iteration.
public static void RegisterInterfaceTypes(this Container container, Assembly assembly)
{
assembly.GetExportedTypes()
.Select(t => new {
Type = t,
Interface = t.GetInterfaces().FirstOrDefault()
})
.ToList()
.ForEach(t =>
{
container.Register(t.Interface, t.Type, Lifestyle.Transient);
});
}
We also have lazy classes to register. We can register these classes like below one by one. But we want to register all lazy types with similar iteration using reflection.
container.Register(() => new Lazy<ICommonBusiness>(container.GetInstance<CommonBusiness>));
You can make use of the ResolveUnregisteredType extension method to make last-minute registrations for resolve Lazy<T> dependencies:
Source:
public static void AllowResolvingLazyFactories(this Container container)
{
container.ResolveUnregisteredType += (sender, e) =>
{
if (e.UnregisteredServiceType.IsGenericType &&
e.UnregisteredServiceType.GetGenericTypeDefinition() == typeof(Lazy<>))
{
Type serviceType = e.UnregisteredServiceType.GetGenericArguments()[0];
InstanceProducer registration = container.GetRegistration(serviceType, true);
Type funcType = typeof(Func<>).MakeGenericType(serviceType);
Type lazyType = typeof(Lazy<>).MakeGenericType(serviceType);
var factoryDelegate = Expression.Lambda(funcType, registration.BuildExpression()).Compile();
var lazyConstructor = (
from ctor in lazyType.GetConstructors()
where ctor.GetParameters().Length == 1
where ctor.GetParameters()[0].ParameterType == funcType
select ctor)
.Single();
var expression = Expression.New(lazyConstructor, Expression.Constant(factoryDelegate));
var lazyRegistration = registration.Lifestyle.CreateRegistration(
serviceType: lazyType,
instanceCreator: Expression.Lambda<Func<object>>(expression).Compile(),
container: container);
e.Register(lazyRegistration);
}
};
}
Usage:
container.AllowResolvingLazyFactories();
But please note the warnings from the documentation:
Warning: Registering [Lazy<T>] by default is a design smell. The use of [Lazy<T>] makes your design harder to follow and your system harder to maintain and test. Your system should only have a few of those [...] at most. If you have many constructors in your system that depend on a [Lazy<T>], please take a good look at your dependency strategy. The following article goes into details about why [this is] a design smell.
Warning: [...] the constructors of your components should be simple, reliable and quick (as explained in this blog post by Mark Seemann). That would remove the need for lazy initialization. For more information about creating an application and container configuration that can be successfully verified, please read the How To Verify the container’s configuration.

Why is Structuremap's Transient lifecycle treated like ContainerScoped on nested containers?

I have the following class declaration and unit test:
public class Blah { }
[TestMethod]
public void TestMethod1()
{
var container = new Container();
var instance1 = container.GetInstance<Blah>();
var instance2 = container.GetInstance<Blah>();
var areBothInstancesSame = instance1 == instance2;
var nested = container.GetNestedContainer();
var nestedInstance1 = nested.GetInstance<Blah>();
var nestedInstance2 = nested.GetInstance<Blah>();
var areBothNestedInstancesSame = nestedInstance1 == nestedInstance2;
}
When I run this test, areBothInstancesSame is false but areBothNestedInstancesSame is true.
I also tested this inside a Web Api controller action:
public class Blah { }
public IHttpActionResult GetBlah()
{
var scope = this.Request.GetDependencyScope();
var instance1 = (Blah)scope.GetService(typeof(Blah));
var instance2 = (Blah)scope.GetService(typeof(Blah));
var areBothInstancesSame = instance1 == instance2;
return this.Ok();
}
And again, areBothInstancesSame is true.
I see this described in Structuremap's documentation, so I believe it's working as intended, but I don't understand why this is intended or how to get the nested container that Web Api automatically creates to return a new instance for each service with a Transient lifecycle.
Can anyone help me understand: 1) why this is the intended default behavior and how to make the nested container return a new instance every time; or 2) why it's obvious that I should never want the nested container to return a new instance every time?
Thanks
The best answer I can give is that the word nested refers rather to container's services and not necessarily to container hierarchy as it may seem (that is why child containers exist also)
Getting a service instance from a normal container will create a new instance along with the full object graph, with all required nested services inside. No mater how may times some transient service is nested inside the object graph, only one instance is created for that service type and reused within the entire graph.
For a nested container the transient instances behave as they belong to(are nested inside) the same object graph because it's purpose is to be used within one logical request.
maybe this example will help with the usage of nested containers http://structuremap.github.io/the-container/nested-containers/#sec5
basically nested containers exist to ensure transient services will not get a new instance with each GetService call.
To make a nested container return a new instance every time you should register the service as AlwaysUnique

Effective way to invoke generic interface method in runtime

I'm working on the some kind of EventSourcing architecture and have 2 main concepts in my app - events and handlers.
Events example:
class NewRecordCreated: EventMessage {...}
And there some handlers looks like:
class WriteDBHandler: IEventHandler<NewRecordCreated>, IEventHandler<RecordUpdated> {
public void Handle(NewRecordCreated eventMessage) {...}
public void Handle(RecordUpdated eventMessage) {...}
}
And also I have custom implementation of queue protocol which dispatch events to proper handlers. So basically on app startup I parse assembly and create mapping between event and handlers based on types.
So when I actually dispatching events to handlers I based on event type getting chain of handler's types - something like var handlerChain = [typeof(WriteDbHandler), typeof(LogHandler), typeof(ReadModelUpdateHandler)] and for each of those handlers I need to invoke it's instance, then cast it to proper interface (IEventHandler<>) and than invoke Handle method.
But I can't cast to generic interface, since it's not possible. I think about options of implementing non generic version of interface, but it's seems quite unpleasant for me to add extra method implementation each time, especially if there no any real reasons for it.
I think about dynamic invocation or reflection, but both of this variants seems have performance issues. Maybe you could advice me some suitable alternatives?
Using reflection
Rather than trying to cast to IEventHandler<>, you can instead use reflection to get a reference to the method you need to invoke. The code below is a good example. It simplifies the "queue protocol" for sake of brevity, but it should sufficiently illustrate the reflection that you need to do.
class MainClass
{
public static void Main(string [] args)
{
var a = Assembly.GetExecutingAssembly();
Dictionary<Type, List<Type>> handlerTypesByMessageType = new Dictionary<Type, List<Type>>();
// find all types in the assembly that implement IEventHandler<T>
// for some value(s) of T
foreach (var t in a.GetTypes())
{
foreach (var iface in t.GetInterfaces())
{
if (iface.GetGenericTypeDefinition() == typeof(IEventHandler<>))
{
var messageType = iface.GetGenericArguments()[0];
if (!handlerTypesByMessageType.ContainsKey(messageType))
handlerTypesByMessageType[messageType] = new List<Type>();
handlerTypesByMessageType[messageType].Add(t);
}
}
}
// get list of events
var messages = new List<EventMessage> {
new NewRecordCreated("one"),
new RecordUpdated("two"),
new RecordUpdated("three"),
new NewRecordCreated("four"),
new RecordUpdated("five"),
};
// process all events
foreach (var msg in messages)
{
var messageType = msg.GetType();
if (!handlerTypesByMessageType.ContainsKey(messageType))
{
throw new NotImplementedException("No handlers for that type");
}
if (handlerTypesByMessageType[messageType].Count < 1)
{
throw new NotImplementedException("No handlers for that type");
}
// look up the handlers for the message type
foreach (var handlerType in handlerTypesByMessageType[messageType])
{
var handler = Activator.CreateInstance(handlerType);
// look up desired method by name and parameter type
var handlerMethod = handlerType.GetMethod("Handle", new Type[] { messageType });
handlerMethod.Invoke(handler, new object[]{msg});
}
}
}
}
I compiled this and ran it on my machine and got what I believe are the correct results.
Using run-time code generation
If reflection is not fast enough for your purposes, you can compile code on-the-fly for each input message type and execute that.
The System.Reflection.Emit namespace has facilities for doing just that.
You can define a dynamic method (not to be confused with the dynamic keyword, which is something else), and emit a sequence if IL opcodes that will run each handler in the list in sequence.
public static Dictionary<Type, Action<EventMessage>> GenerateHandlerDelegatesFromTypeLists(Dictionary<Type, List<Type>> handlerTypesByMessageType)
{
var handlersByMessageType = new Dictionary<Type, Action<EventMessage>>();
foreach (var messageType in handlerTypesByMessageType.Keys)
{
var handlerTypeList = handlerTypesByMessageType[messageType];
if (handlerTypeList.Count < 1)
throw new NotImplementedException("No handlers for that type");
var method =
new DynamicMethod(
"handler_" + messageType.Name,
null,
new [] { typeof(EventMessage) });
var gen = method.GetILGenerator();
foreach (var handlerType in handlerTypeList)
{
var handlerCtor = handlerType.GetConstructor(new Type[0]);
var handlerMethod =
handlerType.GetMethod("Handle", new Type[] { messageType });
// create an object of the handler type
gen.Emit(OpCodes.Newobj, handlerCtor);
// load the EventMessage passed as an argument
gen.Emit(OpCodes.Ldarg_0);
// call the handler object's Handle method
gen.Emit(OpCodes.Callvirt, handlerMethod);
}
gen.Emit(OpCodes.Ret);
var del = (Action<EventMessage>)method.CreateDelegate(
typeof(Action<EventMessage>));
handlersByMessageType[messageType] = del;
}
}
Then, instead of invoking the handlers with handlerMethod.Invoke(handler, new object[]{msg}), you just call the delegate like any other, with handlersByMessageType[messageType](msg).
Full code listing here.
The actual code generation is done in the GenerateHandlerDelegatesFromTypeLists method.
It instantiates a new DynamicMethod, gets its associated ILGenerator, and then emits opcodes for each handler in turn.
For each handler type, it will instantiate a new object of that handler type, load the event message onto the stack, and then execute the Handle method for that message type on the handler object.
This is of course assuming that the handler types all have zero-parameter constructors.
If you need to pass arguments to the constructors, though, you'll have to modify it considerably.
There are other ways to speed this up even more.
If you relax the requirement to create a new handler object with every message, then you could just create the objects while generating the code, and load them.
In that case, replace gen.Emit(OpCodes.Newobj, handlerCtor) with gen.Emit(OpCodes.Ldobj, handlerObjectsByType[handlerType]).
That gives you two benefits:
1. you're avoiding an allocation on every message
2. you can instantiate the objects any way you want when you populate the handlerObjectsByType dictionary. You can even use constructors with parameters or factory methods.

In TPL Dataflow, is it possible to change DataflowBlockOptions after block is created but before it is used?

... and have it take effect?
I'd like to defer setting the ExecutionDataflowBlockOptions.SingleProducerConstrained property until I'm ready to link the network together. (Because, I want to separate creating the blocks, with their semantics, from linking the network together, with its semantics.)
But as far as I can tell you can only set the ExecutionDataflowBlockOptions when the block is created (e.g., for TransformBlock, TransformManyBlock, etc, you pass it in to the constructor and it is not visible otherwise).
However ... it hasn't escaped my notice that the properties have public setters. So ... can I create the block with a placeholder instance of ExecutionDataflowBlockOptions and hold on to it so that I can later set SingleProducerConstrained=true if I desire, when linking the blocks together (and that it will take effect)?
(BTW, is there any way to tell if SingleProducerConstrained is having any effect other than measuring throughput?)
Update: #i3amon correctly pointed out in his answer this can't be done because dataflow blocks clone the DataflowBlockOptions you pass in and use that. But I did it anyway, using internal data structures I can access via reflection and dynamic. I put that in an answer below.
It isn't possible. Modifying the options after the fact won't work. The options are cloned inside the block's constructor. Changing the options later will have no effect.
You can see examples of that here and here and it's simple to verify:
var options = new ExecutionDataflowBlockOptions
{
NameFormat = "bar",
};
var block = new ActionBlock<int>(_ => { }, options);
options.NameFormat = "hamster";
Console.WriteLine(block.ToString());
Output:
bar
Let me answer my own question. Using information from DotNetInside's decompile of the Dataflow assembly, for example, TransformBlock here (thanks #i3amon again for the link to dotnetinside.com), and the very nice ExposedObject package at codeplex here (which I learned about at this blog post, I did the following:
The TPL Dataflow blocks all implement debugger visualizers via the DebuggerTypeProxy attribute, which, applied to a type, names another type to use in the Visual Studio debugger whenever the original type is to be displayed (e.g., watch window).
Each of these DebuggerTypeProxy-named classes are inner classes of the dataflow block the attribute is attached to, usually named DebugView. That class is always private and sealed. It exposes lots of cool stuff about the dataflow block, including its genuine (not a copy) DataflowBlockOptions and also - if the block is a source block - an ITargetBlock[], which can be used to trace the dataflow network from its start block after construction.
Once you get an instance of the DebugView you can use dynamic via ExposedObject to get any of the properties exposed by the class - ExposedObject lets you take an object and use ordinary method and property syntax to access its methods and properties.
Thus you can get the DataflowBlockOptions out of the dataflow block and change its NameFormat, and if it is an ExecutionDataflowBlockOptions (and you haven't yet hooked up the block to other blocks) you can change its SingleProducerConstrained value.
However you can't use dynamic to find or construct the instance of the inner DebugView class. You need reflection for that. You start by getting the DebuggerTypeProxy attribute off your
dataflow block's type, fetch the name of the debugging class, assume it is an inner class of
the dataflow block's type and search for it, convert it to a closed generic type, and finally
construct an instance.
Be fully aware that you're using undocumented code from the dataflow internals. Use your own
judgement about whether this is a good idea. In my opinion, the developers of TPL Dataflow did a lot of work to support viewing these blocks in the debugger, and they'll probably keep it up. Details may change, but, if you're doing proper error checking on your reflection and dynamic use of these types, you will be able to discover when your code stops working with a new version of TPL Dataflow.
The following code fragments probably don't compile together - they're simply cut&pasted out of my working code, from different classes, but they certainly give you the idea. I made it work fine. (Also, for brevity, I elided all error checking.) (Also, I developed/tested this code with version 4.5.20.0 only of TPL dataflow, so you may have to adapt it for past - or future! - versions.)
// Set (change) the NameFormat of a dataflow block after construction
public void SetNameFormat(IDataflowBlock block, string nameFormat)
{
try
{
dynamic debugView = block.GetInternalData(Logger);
if (null != debugView)
{
var blockOptions = debugView.DataflowBlockOptions as DataflowBlockOptions;
blockOptions.NameFormat = nameFormat;
}
}
catch (Exception ex)
{
...
}
}
// Get access to the internal data of a dataflow block via its DebugTypeProxy class
public static dynamic GetInternalData(this IDataflowBlock block)
{
Type blockType = block.GetType();
try
{
// Get the DebuggerTypeProxy attribute, which names the debug class type.
DebuggerTypeProxyAttribute debuggerTypeProxyAttr =
blockType.GetCustomAttributes(true).OfType<DebuggerTypeProxyAttribute>().Single();
// Get the name of the debug class type
string debuggerTypeProxyNestedClassName =
GetNestedTypeNameFromTypeProxyName(debuggerTypeProxyAttr.ProxyTypeName);
// Get the actual Type of the nested class type (it will be open generic)
Type openDebuggerTypeProxyNestedClass = blockType.GetNestedType(
debuggerTypeProxyNestedClassName,
System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic);
// Close it with the actual type arguments from the outer (dataflow block) Type.
Type debuggerTypeProxyNestedClass =
openDebuggerTypeProxyNestedClass.CloseNestedTypeOfClosedGeneric(blockType);
// Now create an instance of the debug class directed at the given dataflow block.
dynamic debugView = ExposedObject.New(debuggerTypeProxyNestedClass, block);
return debugView;
}
catch (Exception ex)
{
...
return null;
}
}
// Given a (Type of a) (open) inner class of a generic class, return the (Type
// of the) closed inner class.
public static Type CloseNestedTypeOfClosedGeneric(
this Type openNestedType,
Type closedOuterGenericType)
{
Type[] outerGenericTypeArguments = closedOuterGenericType.GetGenericArguments();
Type closedNestedType = openNestedType.MakeGenericType(outerGenericTypeArguments);
return closedNestedType;
}
// A cheesy helper to pull a type name for a nested type out of a full assembly name.
private static string GetNestedTypeNameFromTypeProxyName(string value)
{
// Expecting it to have the following form: full assembly name, e.g.,
// "System.Threading...FooBlock`1+NESTEDNAMEHERE, System..."
Match m = Regex.Match(value, #"^.*`\d+[+]([_\w-[0-9]][_\w]+),.*$", RegexOptions.IgnoreCase);
if (!m.Success)
return null;
else
return m.Groups[1].Value;
}
// Added to IgorO.ExposedObjectProject.ExposedObject class to let me construct an
// object using a constructor with an argument.
public ExposedObject {
...
public static dynamic New(Type type, object arg)
{
return new ExposedObject(Create(type, arg));
}
private static object Create(Type type, object arg)
{
// Create instance using Activator
object res = Activator.CreateInstance(type, arg);
return res;
// ... or, alternatively, this works using reflection, your choice:
Type argType = arg.GetType();
ConstructorInfo constructorInfo = GetConstructorInfo(type, argType);
return constructorInfo.Invoke(new object[] { arg });
}
...
}

Creating a new instance of an object each time method is called

Messenger.Default.Register<OpenWindowMessage>(this, message =>
{
var adventurerWindowVM = SimpleIoc.Default.GetInstance<AdventurerViewModel>();
adventurerWindowVM.Adv = message.Argument;
var adventurerWindow = new AdventurerView()
{
DataContext = adventurerWindowVM
};
adventurerWindow.Show();
});
This code is fairly simple; it just opens a new window and sets the DataContext of the new window. The problem I'm having is that if I execute this twice, the content of the first instance will be overwritten and be set to that of the second since adventurerWindowVM is the DataContext of both windows and it is overwritten each time this code is called. I'm looking for a way to prevent this; I'd like to be able to open multiple windows using this message and have each of them be unique, but thus far I haven't figured out a way to do so. Any advice would be greatly appreciated. I apologize for the vague title; I was unsure of what to name this question. (Also, I know that this isn't a method. What would this block of code be called?)
Update: I'm using MVVM Light and my code is based off of an example somebody provided for me in this answer: https://stackoverflow.com/a/16994523/1667020
Here is some code from my ViewModelLocator.cs
public ViewModelLocator()
{
_main = new MainViewModel();
ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default);
SimpleIoc.Default.Register<GameViewModel>();
SimpleIoc.Default.Register<AdventurerViewModel>();
}
Having given the other answer, I guess I can say the IoC container used here is just SimpleIoC from MvvmLight and to get a new instance of the VM on every GetInstance(...) all you need to do is pass in a unique key every time when trying to resolve an instance of the VM.
So you can switch
var adventurerWindowVM = SimpleIoc.Default.GetInstance<AdventurerViewModel>();
to
var adventurerWindowVM = SimpleIoc.Default.GetInstance<AdventurerViewModel>(System.Guid.NewGuid().ToString());
However as mentioned by the author of MVVMLight Here these VM's will get cached and we need to get rid of them when no longer needed. In your case probably when the Window is closed.
Thus I'd have that entire lambda something like:
Messenger.Default.Register<OpenWindowMessage>(this, message =>
{
var uniqueKey = System.Guid.NewGuid().ToString();
var adventurerWindowVM = SimpleIoc.Default.GetInstance<AdventurerViewModel>(uniqueKey);
adventurerWindowVM.Adv = message.Argument;
var adventurerWindow = new AdventurerView()
{
DataContext = adventurerWindowVM
};
adventurerWindow.Closed += (sender, args) => SimpleIoc.Default.Unregister(uniqueKey);
adventurerWindow.Show();
});
Note:
While this is somewhat longer 3 lines compared to just creating a new VM yourself with (new AdventurerViewModel()) I still favor this because if you use an IoC container to manage LifeTime of your VM's, then have it manage them completely. Don't really like mix-n-match when not needed. Rather keep the IoC Container doing what it's meant to do.
If you need more control over VM injection and Life-time management look at more sophisticated Ioc controllers such as Unity. SimpleIoC was just meant to be a simple get your feet "wet" in IoC kind of container and it does a very good job in that regard.
I think you are trying to use the same instance of your ViewModel with multiple views. So the views will obviously overwrite each others viewmodel contents.
What if you do this;
Messenger.Default.Register<OpenWindowMessage>(this, message =>
{
var adventurerWindowVM = new AdventurerViewModel();
adventurerWindowVM.Adv = message.Argument;
var adventurerWindow = new AdventurerView()
{
DataContext = adventurerWindowVM
};
adventurerWindow.Show();
});
It's a method call, passing in an anonymous method using a lambda expression.
It looks like you are getting your AdventurerViewModel from some sort of IoC container. How is the IoC container configured? In particular, what is the scope of the objects it gives you back? If you have the IoC configured to create objects in singleton scope, for example, then you will always get back a reference to the same object each time. You may need to configure the scope of the object in your IoC container so that it gives you back a fresh copy every time.
How you do that will depend on your IoC container. Without knowing which IoC framework you are using or seeing its configuration, it's impossible to make any further comment.
My advice would be to create an extension method for SimpleIOC. Something like this:
public static T CreateInstance<T>(this SimpleIoc simpleIoc)
{
// TODO implement
}
You already know the method to get the same instance; extended SimpleIoc with a method to create a new instance:
T instance = SimpleIoc.Default.GetInstance<T>();
T createdInstance = SimpleIoc.Defalt.CreateInstance<T>();
If you are not familiar with extension methods, see Extension Methods Demystified
The implementation:
Of type T, get the constructor.
If there is more than one constructor: either throw exception, or decide which constructor to use. Simple method: use the same method that is used in SimpleIoc.GetInstance, with an attribute. More elaborate method: try to find out if you can find registered elements that match one of the constructors. This is not explained here.
Once you've found the constructor that you need, get its parameters.
Ask SimpleIoc for instances of this parameter, or if they should be new also, ask SimpleIoc to create new instances.
CreateInstance
.
public static T CreateInstance<T>(this SimpleIoc ioc)
{
return (T)ioc.CreateInstance(typeof(T));
}
public static object CreateInstance(this SimpleIoc ioc, Type type)
{
ConstructorInfo constructor = ioc.GetConstructor(type);
IEnumerable<object> constructorParameterValues = ioc.GetParameters(constructor);
constructor.Invoke(constructorParameterValues.ToArray());
}
To decide which constructor to use:
private static ConstructorInfo GetConstructor(this SimpleIoc ioc, Type type)
{
ConstructorInfo[] constructors = type.GetConstructors();
ConstructorInfo constructorToUse;
if (constructorInfo.Length > 1)
{
// Decide which constructor to use; not explained here
// use Attribute like SimpleIoc.GetInstance?
// other method: use SimpleIoc.IsRegistered to check which Parameters
// are registered: use ConstructorInfo.GetParameters()
constructorToUse =
}
else
constructorToUse = constructoInfo[0];
return constructorToUse;
}
To get the values of the parameters in the constructor, we need to decide whether we want existing values from Ioc, or create new values:
public static IEnumerable<object> GetParameterValues(this simpleIoc ioc,
ConstructorInfo constructor)
{
IEnumerable<Type> parameterTypes = contructor.GetParameters()
.Select(parameter => parameter.ParameterType);
return ioc.GetInstances(parameterTypes);
}
public static IEnumerable<object> GetInstances(this SimpleIoc ioc,
IEnumerable<Type> types)
{
// TODO: decide if we want an existing instance from ioc,
// or a new one
// use existing instance:
return types.Select(type => ioc.GetInstance(type));
// or create a new instance:
return types.Select(type => ioc.CreateInstance(type));
}
This seems like a lot of code, but most of it is comment and most methods are one liners.

Categories

Resources