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.
Related
I currently have a case where I have multiple customers who have variability of on what forms of notifications they want (ie email, fax, etc.). They could also want one or more than one. So I have created a factory with some basic Reflection that will dynamically create concrete classes depending on some parameters that get sent in through the customer profile. I'm curious is there a better way to do this using ASP.Net Core Dependency Injection? I have put in the factory code here to help folks understand of what I'm trying to do.
The customer profile will send in a string array of what services they have subscribed as a parameter to CreateInstances so only specific services would be dynamically created.
public Dictionary<string, Type> Notifications;
public NotificationFactory()
{
LoadTypes();
}
public IEnumerable<INotificationService> CreateInstances(params string[] namesOfServices)
{
var servicesToInstantiate = namesOfServices.ToList();
List<INotificationService> result = new List<INotificationService>();
foreach (var service in servicesToInstantiate)
{
Type serviceName = GetServiceNameToCreate(service.ToLower());
if (serviceName != null)
{
result.Add(Activator.CreateInstance(serviceName) as INotificationService);
}
}
return result;
}
private Type GetServiceNameToCreate(string NotificationClassName)
{
return Notifications.FirstOrDefault(a => a.Key.Contains(NotificationClassName)).Value;
}
protected virtual void LoadTypes()
{
Notifications = Assembly.GetExecutingAssembly().GetTypes()
.Where(t => typeof(INotificationService).IsAssignableFrom(t) && !t.IsInterface)
.ToDictionary(t => t.Name.ToLower(), t => t);
}
It is a bad idea to take an arbitrary string and activate an instance the way you are doing it. The string should at least be white-listed. If a malicious user were able to tamper with the strings in the database, for example, they could choose what type to activate and potentially trigger unauthorized behavior or denial of service.
Instead, define a white list of types, and associate each type with a delegate that constructs the service you need.
var map = new Dictionary<string,Func<INotificationService>>
{
{ "EMAIL" : () => new EmailService() },
{ "PHONE" : () => new PhoneService() }
};
Then to get a service, call
if (!map.ContainsKey(serviceType)) throw new ArgumentException(nameof(serviceType));
INotificationService service = map[serviceType]();
Or if you prefer:
Func<INotificationService> factory;
if (!map.TryGetValue(serviceType, out factory)) throw new ArgumentException(nameof(serviceType));
INotificationService service = factory();
This way you are certain that the service type is one that you support, and you don't need to use any Reflection.
If you need more extensibility
If you want to be able to add more delivery methods without changing the code that populates map, you can of course populate the map from a configuration file. Although I'm left wondering how you could possibly implement a new delivery method without changing any code, and whether you have a bone fide NFR that requires you to be able to. Seems to me that new delivery methods don't get added very often and would be a big deal in other respects, so there is little point in saving yourself adding one line of code here.
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
I apologize in advance if this is a dumb question: I am quite new to NInject.
I need to initialize my application with several collections, each having several identical objects. Without IoC, that would look like:
public ICollection<ICollection<IBusinessObject>> Piles = new ICollection<ICollection<IBusinessObject>>();
public MyCollectionContainer()
{
Piles.Add(new List<IBusinessObject>({ new ObjectA(), new ObjectA() });
Piles.Add(new List<IBusinessObject>({ new ObjectB(), new ObjectB() });
Piles.Add(new List<IBusinessObject>({ new ObjectC(), new ObjectC() });
}
I'd like to instruct NInject to do that job for me, so that a call to Kernel.Get<MyCollectionContainer>() would do the same job as above, with some extra flexibility, of course.
In other words, I want, at bind time, to instruct NInject to
Kernel.Bind<ICollection<ICollection<IBusinessObject>>>().To< /* A list of 3 */>();
Kernel.Bind<IList<IBusinessObject>>().To< /* A List of 2 IBusinessObject */>();
Kernel.Bind<IBusinessObject>().To< /* a different type depending on the container */>();
Side question: Should I better use Kernel.Get<MyCollectionContainer>() or Kernel.Get<ICollection<ICollection<IBusinessObject>>>()
EDIT: While searching for a solution, I tried to define a custom binding for my collections in the model of
Kernel.Bind<IList<IBusinessObject>>()
.ToConstructor(x => new List<IBusinessObject>(
x.Inject<IList<IBusinessObject>>())
);
With an extension method IConstructorArgumentSyntax.InjectMany(int i):
Kernel.Bind<IList<IBusinessObject>>().To<ObjectA>();
Kernel.Bind<IList<IBusinessObject>>()
.ToConstructor(x => new List<IBusinessObject>(
x.InjectMany<IList<IBusinessObject>>(2))
);
public static T InjectMany<T>(this IConstructorArgumentSyntax x, int numberOfInjections)
{
/* loop */
{
x.Inject<T>();
}
}
Sadly NInject refuses to call x.Inject(); complaining that I've dived too deep into their magic:
System.InvalidOperationException :
This method is for declaration that a parameter shall
be injected only! Never call it directly.
Question
I have a full name of a type, for example "StrategyA",and I want to get new Strategy(value) that assigned to its interface "IStrategy", how to get it?
What I have tries
I have tried this:
IStrategy strategy;
if (strategyName == "StrategyA")
{
strategy = new StrategyA(value);
}
else if(strategyName == "StrategyB")
{
strategy = new StrategyB(date);
}
...
but when I create a new strategy , I have to add another branch to the code, and I think it is a bad code style.
Is there any better way to solve this problem?
Here are a few options, in no particular order:
(A) If your strategy name is a full CLR type name (or a full type name may be determined by convention), and each strategy has common constructor parameters, you can find the type using reflection and create an instance.
Type strategyType = Type.GetType(strategyName)
IStrategy instance = (IStrategy)Activator.CreateInstance(strategyType, paramArray);
Be aware that you should not use this approach if you cannot trust the strategyName input, otherwise you may be creating instances of unexpected types.
(B) You could create a mapping from strategy name to factory delegate using a dictionary. This approach may be useful if various constructors are used, or if factories come and go.
Dictionary<string, Func<IStrategy>> factories = new Dictionary<string, Func<IStrategy>>();
//register various factories
factories.Add("StrategyA", () => new StrategyA(value));
factories.Add("StrategyB", () => new StrategyB(date));
Func<IStrategy> factory;
if(factories.TryGetValue(strategyName, out factory))
{
IStrategy instance = factory();
}
(C) You could rely on any number of IoC containers such as Autofac, and ask for the corresponding IStrategy implementation.
(D) Another related pattern that is sometimes used relies on implementations of IStrategy to check applicability and returning the first one which is applicable. This can be useful when the caller doesn't know which strategy to pick.
List<IStrategy> strategies = new List<IStrategy>();
//register strategies (highest priority first)
strategies.Add(new StrategyA(value));
strategies.Add(new StrategyB(value));
//alternatively, you might resolve IEnumerable<IStrategy> from your IoC container
foreach(IStrategy strategy in strategies)
{
if(strategy.IsApplicable(someInput)) return strategy;
}
You would do
strategy = (IStrategy)Activator.CreateInstance(Type.GetType(strategyName));
Why don't you use Reflection.
Some thing like :
Type type = Type.GetType(strategyName, true);
// create an instance of that type
object instance = Activator.CreateInstance(type);
There are various ways of doing it.
1) Simple switch case, if your conditions are less
2) IOC containers. http://www.hanselman.com/blog/ListOfNETDependencyInjectionContainersIOC.aspx or Unity container provided by microsoft http://msdn.microsoft.com/en-us/library/ff649614.aspx
3) Activator.CreateInstance(type);
4) You can customize your own using factory design pattern
Try Constructor Injection (part of Dependency Injection)
E.g.
public class MyStrategy
{
IStrategy strategy;
public MyStrategy(IStrategy concreteImplementation)
{
this.strategy = concreteImplementation;
}
}
In this way you can pass any object that implements IStrategy interface. So you could eliminate the If...else conditions in your constructor. The usage of this is as follows.
StrategyA strategyA = new StrategyA(value);
MyStrategy myStrategyA = new MyStrategy(strategyA);
StrategyB strategyB = new StrategyB(date);
MyStrategy myStrategyB = new MyStrategy(strategyB);
StrategyC strategyC = new StrategyC(someValue);
MyStrategy myStrategyC = new MyStrategy(strategyC);
Hope this helped!
I have an Interface that is implemented by several types. But before I do a kernel.GetAll<IAmServiceable>() I want to be able to ponder the target types of the injection.
I know the function kernel.GetBindings(typeof(IAmServiceable)) exists but this returns a list of IBinding's.
Does anyone know how I can get the target type from the IBinding?
I want to know the type that is bound to IAmServiceable before it gets instantiated.
I know it's probably a bit late now for your problem, but since i ran into this today, i thought others might too.
That's the code i finally came up with - i don't think its perfect (far from it), especially regarding performance, but it works for my case, and since i do not intend to call this method very often, it seems ok to me.
public Type GetBoundToType(IKernel kernel, Type boundType)
{
var binding = kernel.GetBindings(boundType).FirstOrDefault();
if (binding != null)
{
if (binding.Target != BindingTarget.Type && binding.Target != BindingTarget.Self)
{
// TODO: maybe the code below could work for other BindingTarget values, too, feelfree to try
throw new InvalidOperationException(string.Format("Cannot find the type to which {0} is bound to, because it is bound using a method, provider or constant ", boundType));
}
var req = kernel.CreateRequest(boundType, metadata => true, new IParameter[0], true, false);
var cache = kernel.Components.Get<ICache>();
var planner = kernel.Components.Get<IPlanner>();
var pipeline = kernel.Components.Get<IPipeline>();
var provider = binding.GetProvider(new Context(kernel, req, binding, cache, planner, pipeline));
return provider.Type;
}
if (boundType.IsClass && !boundType.IsAbstract)
{
return boundType;
}
throw new InvalidOperationException(string.Format("Cannot find the type to which {0} is bound to", boundType));
}
This is not possible. E.g what is the type In this case?
Bind<IX>().ToMethod(c => RandomBool() ? new Foo() : new Bar());
If you are working within a NinjectModule (or have access to an IKernel some other way) A nice simple approach would be:
var concreteType = Kernel.Get<InterfaceType>().GetType();
Obviously, the downside is you create an instance of the concrete type. It is nevertheless nice and simple and I think pretty robust. Obviously, if the interface derives from IDisposable you would use a using statement:
using(var obj = Kernel.Get<InterfaceType>())
{
var concreteType = obj.GetType();
.
.
.
}