The Converter property in the code from the blog post, Silverlight MultiBinding solution for Silverlight 4, is not a dependency property, so I can't bind it with a converter (that for technical reasons must be instantiated as part of Unity injection earlier in the application rather than as a simple static resource as part of a user control).
How can I modify the MultiBinding code to accept a bound converter? I tried to make it a dependency property:
public IMultiValueConverter Converter { get { return (IMultiValueConverter)GetValue(ConverterProperty); } set { SetValue(ConverterProperty, value); } }
public static DependencyProperty ConverterProperty = DependencyProperty.Register("Converter", typeof(IMultiValueConverter), typeof(IMultiValueConverter), null);
but I got
DependencyProperty System.Windows.Data.IMultiValueConverter. Converter cannot be set on an object of type ...Binding.MultiBinding.
If this is not a viable option, how can I bind the ConverterParameter property or get something to simulate bindings of a converter to a MultiBinding?
I solved this using the "simulated bindings" route, though that's not my preference if someone has another answer. What I did instead was not build up the converter via dependency injection, but instead had it use service location to get it's needed dependencies. Generally I prefer dependency injection to service location. The "service location" was a matter of storing the Unity container in the application's global resources; from there it's not difficult to get what I need.
Related
Requiring to sometimes use dependency injection in ActioFilter or other attributes running before or after an action API or result is inevitable. However, it is carried out through passing the type to be injected to the attribute using the typeof keyword. In order to simplify the case, when having various implementations for an interface, I have found it much simpler to manually instantiate the type than using the built-in dependency injection framework. For example:
public TestAttribute: Attribute, IActionFilter {
private Type injectionType;
public TestAttribute(Type injectionType){
...
}
...
public void OnActionExecuting(ActionExecutingContext context) {
InjectedTypeInterface injectedTypInterface = (InjectedTypeInterface) Activator.CreateInstance(injectedType, arg1, arg2, ...);
...
}
}
I want to know, from the point of view of other people here, that would this approach cause problems that using the built-in dependency injection framework would not? (Injected implementation will be always Transient in this case and not Scoped or Singleton)
I don't recommend doing the route of Activator.CreateInstance, here are some reasons why to avoid it and stick with the official way:
You'd need to pass in all instances of the parameters (i.e. of the type you want to instantiate has other dependencies) to it
The instance created this way isn't tracked by the scoped container. This also means, it won't automatically get disposed (Updated note this of course will only happen if the service implements IDisposable interface) at the end of the request and instead be disposed at some indeterminable time in future, when the GC kicks in and will keep resources open for longer then intended (i.e. holding connection or file handle open for longer then intended) unless you dispose it explicitly
Like you already recognized, you can't do so with scoped and singleton instances
For your concrete examples, there are easier ways to get a specific instance from DI - aside from the official supported ways (Filters - Dependency Injection) - you can also resolve from HttpContext, assuming you have access to it in the type of filter you are using.
For ActionFilter/IActionFilter
public void OnActionExecuting(ActionExecutingContext context) {
InjectedTypeInterface injectedTypInterface = context.HttpContext
.RequestServices.GetService<InjectedTypeInterface>();
...
}
I previously had the setup for property injection in one of my attributes as
Container.RegisterInitializer<PermitAttribute>(initialize =>
{
initialize.QueryProcessor = Container.GetInstance<IQueryProcessor>();
});
And the usage was
public class PermitAttribute : ActionFilterAttribute
{
public IQueryProcessor QueryProcessor { get; set; }
}
but after updating to simpleinjector 2.6.1 The property injection broke. When I am trying to access QueryProcessor object inside PermitAttribute. It resolves null value where as the Simple Injector configuration still has the same property injection via delegate instance .
Is there any breaking change in property injection behavior due to which it was working in v2.5 and its not working anymore in 2.6.1 ?
Update 1:
The Line in the configuration was throwing error for MVC filter provider registration for attributes in v2.6.1
container.RegisterMvcIntegratedFilterProvider();
For that I commented it . And it stopped the property injection working . The property injection was inside one of my attributes . I guess that's the line above which affects it. And its throwing error in v2.6.1
Update 2:
Message
An MVC filter provider has already been registered for a different
Container instance. Registering MVC filter providers for different
containers is not supported by this method.
StackTrace :
at SimpleInjector.SimpleInjectorMvcExtensions.RequiresFilterProviderNotRegistered(Container container)
at SimpleInjector.SimpleInjectorMvcExtensions.RegisterMvcIntegratedFilterProvider(Container container)
at RemsPortal.App_Start.SimpleInjectorInitializer.Initialize() in d:\Projects Work\RemsPortal\V2.0 Web Portal\RemsPortal\App_Start\SimpleInjectorInitializer.cs:line 39
Update 3 :
entire Configuration
public static void Initialize()
{
var container = new Container();
InitializeContainer(container);
container.RegisterMvcIntegratedFilterProvider();
container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
container.Verify();
DependencyResolver.SetResolver(new SimpleInjectorDependencyResolver(container));
}
private static void InitializeContainer(Container Container)
{
Container.RegisterManyForOpenGeneric(typeof(IAsyncCommandHandler<,>),
AppDomain.CurrentDomain.GetAssemblies());
Container.RegisterOpenGeneric(typeof(ITransactionCommandHandler<,>),
typeof(TransactionCommandHandlerDecorator<,>));
Container.RegisterOpenGeneric(typeof(ICommandResult<>),
typeof(CommandHandlerResult<>));
Container.Register<ICommandResolver, CommandResolver>();
Container.Register<DbContext, RemsContext>();
Container.RegisterOpenGeneric(typeof(IPager<>), typeof(PagerModel<>));
//Container.RegisterPerWebRequest<DbContext, RemsContext>();
Container.Register<UserManager<Users, Guid>, RemsUserManager>();
Container.Register<RoleManager<Roles, Guid>, RemsRoleManager>();
Container.Register<IUserStore<Users, Guid>,
UserStore<Users, Roles, Guid, UserLogins, UserRoles, Claims>>();
Container.Register<IRoleStore<Roles, Guid>, RoleStore<Roles, Guid, UserRoles>>();
Container.RegisterManyForOpenGeneric(typeof(IAsyncQueryHandler<,>),
AppDomain.CurrentDomain.GetAssemblies());
Container.RegisterManyForOpenGeneric(typeof(IAsyncQueryHandler<>),
AppDomain.CurrentDomain.GetAssemblies());
Container.RegisterManyForOpenGeneric(typeof(IQueryHandler<,>),
AppDomain.CurrentDomain.GetAssemblies());
Container.RegisterOpenGeneric(typeof(IQueryResult<>), typeof(QueryResult<>));
Container.RegisterOpenGeneric(typeof(IPaginator<>), typeof(Paginator<>));
Container.Register<IPaginator, Paginator>();
Container.RegisterOpenGeneric(typeof(IAsyncQueryHandler<>), typeof(BaseQuery<>));
Container.RegisterOpenGeneric(typeof(IQueryHandler<>), typeof(BaseQuery<>));
Container.Register<IQueryProcessor, QueryProcessor>(Lifestyle.Singleton);
Container.Register<ILog, NLogger>(Lifestyle.Singleton);
Container.RegisterInitializer<PermitAttribute>(initialize =>
{
initialize.QueryProcessor = Container.GetInstance<IQueryProcessor>();
});
Container.RegisterInitializer<BaseController>(initialize =>
{
initialize.QueryProcessor = Container.GetInstance<IQueryProcessor>();
initialize.Logger = Container.GetInstance<ILog>();
});
Container.RegisterInitializer<BaseCommandHandler>(initialize =>
{
initialize.UserManager = Container.GetInstance<RemsUserManager>();
initialize.RoleManager = Container.GetInstance<RemsRoleManager>();
initialize.RemsContext = Container.GetInstance<RemsContext>();
initialize.QueryProcessor = Container.GetInstance<IQueryProcessor>();
});
Container.RegisterInitializer<BaseHandler>(initialize =>
{
initialize.UserManager = Container.GetInstance<RemsUserManager>();
initialize.RolesManager = Container.GetInstance<RemsRoleManager>();
});
}
The exception you are seeing is caused by a verification check that has been added to version 2.6 that prevents you from calling RegisterMvcAttributeFilterProvider and RegisterMvcIntegratedFilterProvider multiple times for different container instances. The problem is described in more details here.
The solution is to make sure RegisterMvcIntegratedFilterProvider is called only once in your code for the duration of the complete app domain and since RegisterMvcAttributeFilterProvider is deprecated, prevent having any calls at all to that legacy method. So if you only have one call in there, set a break point on this line, because you might be calling the Initialize() method twice!
The new RegisterMvcIntegratedFilterProvider allows complete integration of MVC attributes in the Simple Injector pipeline which makes sure that the RegisterInitializer method is called on attributes.
Another option though is to enable explicit property injection for attributes, or to fall back on the use of passive attributes as shown here.
But one note on property injection. I noticed you make extensive use of (explicit) property injection, especially for your base classes. From a design perspective however, it's better to remove the base classes all together, because they are a design smell at least, but might become maintenance problems later on. They might violate the Single Responsibility Principle or at least hide that derived types have too many dependencies, which often means too many responsibilities. I create quite big applications myself with MVC and command handlers and query handlers and I am always able to prevent the use of base classes. If a concrete handler needs a dependency, you should simply inject it into the constructor of that type. Prevent hiding that dependency by (ab)using a base type.
There is one important detail that you should be aware about when you use the RegisterMvcIntegratedFilterProvider. MVC caches filter attributes (god knows why) and this means that such attribute is basically becoming a singleton. This implies that every dependency this filter attribute has, becomes a singleton as well. This is of course be big problem if such dependency is not registered as singleton itself; it becomes a captive dependency. Although Simple Injector contains a diagnostic warning to detect these kinds of errors, Simple Injector will be unable to detect this with attributes, because attributes are not registered in the container. Because of this, my advice is to stay away from using property injection in your attributes at all. We are considering to deprecate the RegisterMvcIntegratedFilterProvider method from the MVC integration library.
As per steven It really was calling the container registration twice .
As I got to see tht
I had called SimpleinjectorInitializer.Initialize(); method in global.asax And then the webactivator also calling the same initizer was taking toll on the simpleinjector which caused the initization to fail for a check .
The solution to that is to remove SimpleinjectorInitializer.Initialize(); from the global.asax and let webactivator do its work .
I am building a WPF based application. I am using Unity to inject all the different dependencies in my application (defined in App.xaml.cs).
In my MainApplication window I have a pretty complex look-less custom control derived from Control(is has about ten more control integrated in it).
I would like to inject a VM into this custom control without coupling it to any other object in my application (except App.xaml.cs of course)
Injection to any WPF window in my application works well, but when I try injecting to the custom control I am facing to different situation:
1. In case I am using
container.RegisterInstance(container.Resolve);
The DI creates a dummy instance of MyCustomControl and injects the VM (using [Dependency] attribute). However this specific instance is not used when I use it in my XAML:
in which case it initializes a new MyCustomControl ignoring any dependencies.
In case I am using
container.RegisterType();
The MyCustomControl completely ignores the injection.
I realize I am probably doing something wrong (not just technically) and I am really trying to avoid coupling this control (which will obviously solve the issue).
I don't know if this is the best solution and found your question while looking for other options but, alas, here is the approach I used to at least get up and running.
I created a base UnityControl class that subclasses Control. In the constructor, I use the ServiceLocator to get a reference to the container. Then I call the BuildUp method to resolve any dependencies on the derived control class. Any dependencies are implemented as read/write properties marked with the DependencyAttribute.
Here's what UnityControl looks like:
public abstract class UnityControl : Control
{
protected UnityControl() : base()
{
Container = ServiceLocator.Current.GetInstance<IUnityContainer>();
Container.BuildUp(this.GetType(), this);
}
protected IUnityContainer Container { get; private set; }
}
I am writing a desktop GIS application and it supports MapXtreme, MS Virtual Earth and our Custom Map Engine.Users of application can change the map engine at run-time by selecting from dropdownlist.I have a Factory class to change map engine like this.
public class MapFactory implements IMapFactory
{
public IMapEngine createInstance(MapType type)
{
if(type==MapType.MapXtreme)
return new MapXtremeEngine();
else if(type==MapType.VirtualEarth)
return new VirtualEarth();
//....other code
}
}
Can I use a Dependency Injection Framework to create suitable MapEngine implementation at run-time by type parameter?
Your example is the exact right pattern for conditionally instantiating an object. Anywhere you need to create an instance, accept IMapFactory in the constructor.
The most a DI framework should do is hand out the IMapFactory instance.
I am a beginner using castle windsor; and kinda introduced to it with Apress Pro Mvc book. In the project that I am working at; I use castlewindsor controller factory instead of mvc controller factory; so i can have parametrized constructors and i can inject the dependencies.
Is there a way to tell the windsorcontroller factory to inject the values to the properties of the controller class without going through constructor?
The reason I want to do this is because I have Logging dependency; Emailler Dependency; Database Dependency; Theme Engine dEpendency; and I dont want to use this many parameters parameter in the constructor.
By default, when Windsor resolves a service implementation, it will populate all properties with public setters that it can satisfy.
However, take notice that sometime it does make sense to put the dependency resolving in the constructor, for that fact that it guarantees that any instance will always be in a valid state. Consider Unit Testing scenario, where the person writing the test will go crazy about the need to know which dependencies should be supplied. When all dependencies goes into the c'tor, the tester will have no choice but to supply the tested instance with all the required dependencies (as stubs or mocks).
Anyway, as for your question, Windsor support C'tor and property injection by default
Castle Windsor will automatically fill any properties with public setters that it knows how to fill.
This means if you have a class
public MyClass {
public SomeDependency {get; set;}
}
As long as the container is configured to know how to resolve SomeDependency it will attempt to resolve and inject it.
Sometimes I've found this default behavior to be hassle. This facility will give you finer grained control over the process.