In Autofac we have PropertiesAutoWired. Its written there
If the component is a reflection component, use the PropertiesAutowired() modifier to inject properties.
Appears that we should use this when we need to do property injection. So I want to know what would it be in case of Ninject.
Ninject doesn't feature an equivalent to Autofacs PropertiesAutowired(). Instead one marks properties with an attribute [Inject] - the binding of the component is unaffected:
public class FooBar
{
// will be injected
[Inject]
public IDependency Dependency { get; set; }
// will not be injected
public IFalaffel Falaffel {get; set;
}
The binding is not affected. For example
Bind<FooBar>().ToSelf();
is perfectly valid and (attributed) properties will be injected.
Also see the Property Injection documentation on the ninject wiki.
Furthermore note, that constructor injection is the preferred alternative. You should only use property injection in case you can't use constructor injection or some other special circumstances, like you cannot get rid of an inheritance hierarchy and don't want to pass constructor parameters down 10 steps in a class hierarchy...
Alternative to using Attributes
If you don't want to clutter your code with references to Ninject, you can also do property injection like this:
Bind<FooBar>().ToSelf()
.OnActivation((ctx, instance) => instance.Dependency = ctx.Kernel.Get<IDependency>());
Related
Is it possible to inject a service into a UserType ?
internal class MyUserType : IUserType
{
private static ISerializer _serializer;
public MyUserType (ISerializer serializer)
{
_serializer = serializer
}
}
Tried the why it is suppose to work for all but fails, stating it needs a default parameterless constructor
I don't think this is going to be possible as you would need to tap into NH's component creation pipeline/process, which, AFAIK, isn't readily exposed.
You could use property injection with a 'local default'. This would allow you to depend on the ISerializer abstraction and replace it when necessary, testing maybe, but rely on a default concrete type in an environment that didn't support IoC.
internal class MyUserType : IUserType
{
private static ISerializer _serializer = new ConcreteSerializer();
public JsonShippingDetailsUserType()
{
}
public ISerializer Serializer { get; set; }
}
N.B. This is a really naive implementation of property injection. If you go with this solution you'll need to 'harden' the code. Mark Seemann's DI book has an excellent example.
The thing is that IUserType is managed by NHibernate which uses its own IoC container and by implication does not have access to your IoC of choice and again by implication does not have access to any services registered on your IoC of choice. There is not easy way of injecting, what I can think of is some sort of proxy or to somehow get access to NHibernate internals.
I've an existing WPF application based on caliburn micro MVVM pattern which was using Ideablade/cocktail for accessing to database. Now I've switched to servicestack and I was keeping on cocktail just for the composition pattern. Since I've noticed it takes quite a bit long to start the application I've done some test and Ninject performs better.
I find extremly usefull the MEF approach of defining the Export/ImportingConstrucor approach but and I was wondering how I can have it with Ninject... is it possible?
In my current implementation I've something as
[Export(typeof(IMyInterface))]
[Export(typeof(MyFirstViewModel))]
public class MyFirstViewModel:IMyInterface
{
[ImportingConstructor]
public MyFirstViewModel(IEventAggregator eventAggregator)รน
{
}
}
I've seend that in ninject I've to define something as
mKernel.Bind<MyFirstViewModel>().To<MyFirstViewModel>();
mKernel.Bind<MyFirstViewModel>().To<MyFirstViewModel>();
Can it be automatic?
Can I also define a funct to resolve when not found?
Thanks
StackTrace :
at Caliburn.Micro.IoC.<.cctor>b__0(Type service, String key) in c:\Users\Rob\Documents \CodePlex\caliburnmicro\src\Caliburn.Micro.Silverlight\IoC.cs:line 13
at Caliburn.Micro.IoC.Get[T](String key) in c:\Users\Rob\Documents\CodePlex\caliburnmicro\src\Caliburn.Micro.Silverlight\IoC.cs:line 32
at myApp.Modules.Core.Framework.ViewModels.myAppScreenBase`1..ctor() in c:\Projects\myApp\branches\myApp-branch-20140526\myApp\Core\Framework\ViewModels\myAppScreenBase.cs:line 44
at myApp.Modules.Core.Framework.ViewModels.myAppSimpleScreen`1..ctor() in c:\Projects\myApp\branches\myApp-branch-20140526\myApp\Core\Framework\ViewModels\myAppSimpleScreen.cs:line 8
at myApp.Modules.AdE.ViewModels.CMATCLIDDelegheViewModel..ctor(IAdERepository repository, IDialogManager dialogManager, ICommonRepository commonRepository) in c:\Projects\myApp\branches\myApp-branch-20140526\myApp\Modules.AdE\ViewModels\CMATCLIDDelegheViewModel.cs:line 56
at DynamicInjector1033b54d439c44dbaa064db1c7e82f18(Object[] )
at Ninject.Activation.Providers.StandardProvider.Create(IContext context)
at Ninject.Activation.Context.ResolveInternal(Object scope)
at Ninject.Activation.Context.Resolve()
at Ninject.KernelBase.<>c__DisplayClass15.<Resolve>b__f(IBinding binding)
at System.Linq.Enumerable.WhereSelectListIterator`2.MoveNext()
at System.Linq.Enumerable.<CastIterator>d__b1`1.MoveNext()
at System.Linq.SystemCore_EnumerableDebugView`1.get_Items()
RepositoryExport :
public class RepositoryBindingGenerator : IBindingGenerator
{
public IEnumerable<IBindingWhenInNamedWithOrOnSyntax<object>> CreateBindings(Type type, IBindingRoot bindingRoot)
{
foreach (var attribute in type.GetCustomAttributes(typeof(RepositoryAttribute), false)
.OfType<RepositoryAttribute>())
{
yield return bindingRoot
.Bind(attribute.ContractType ?? type)
.To(type).InSingletonScope();
}
}
}
but I got this compile error
Error 19 Cannot implicitly convert type 'Ninject.Syntax.IBindingNamedWithOrOnSyntax' to 'Ninject.Syntax.IBindingWhenInNamedWithOrOnSyntax'. An explicit conversion exists (are you missing a cast?)
Depending on the configuration of ninject (by default its enabled) you don't need to bind a type to itself, ninject will resolve it automatically. So mKernel.Bind<MyFirstViewModel>().To<MyFirstViewModel>(); is superfluous. Remark: Creating the binding anyway also works.
However, if you want to bind Bar to IFoo or Foo to IFoo you need to bind it.
With it you can tell ninject to look for all types with an [Export] attribute and bind these.
Here comes the ninject conventions extension to the rescue. Get the ninject.extensions.conventions nuget package.
Then create a convention binding:
kernel.Bind(x => x
.FromThisAssembly()
.SelectAllClasses()
.WithAttribute<ExportAttribute>()
.BindWith<ExportBindingGenerator>());
public class ExportBindingGenerator : IBindingGenerator
{
public IEnumerable<IBindingWhenInNamedWithOrOnSyntax<object>> CreateBindings(Type type, IBindingRoot bindingRoot)
{
foreach (var attribute in type.GetCustomAttributes<ExportAttribute>())
{
yield return bindingRoot
.Bind(attribute.ContractType)
.To(type);
}
}
}
Things get a bit more complicated when you need to also use the [ImportingConstructor] attribute to tell ninject which constructor to use. But i would suppose that you don't need it, since Ninject's auto-constructor-selection. What you can do however is replace all [ImportingConstructor] attributes with Ninject's [Inject] attribute which does exactly the same.
Notes:
You may need to use another method than .FromThisAssembly() to specify all the assemblies which contain the implementation types.
If the implementation types are not public, you need to add IncludeNonePublicTypes() to the convention.
(or "Using LocationInterceptionAspect and IInstanceScopedAspect together")
Using Postsharp I'm trying to inject a property into a target class using 'IntroduceMember' and then using the 'OnGetValue' functionality of LocationInterceptionAspect dynamically give it a value on inspection.
Originally I thought that I'd need two separate aspects, one for the field injection and one for the location interception but managed to combine the two by implementing the IInstanceScopedAspect interface and inheriting from LocationInterceptionAspect.
The problem is that if I set a breakpoint I will see the property that's been injected, but if I set another breakpoint in the OnGetValue method (that gets fired for each property on the class) I can't see it...
Here's some sample code:
[Serializable]
class DALDecoratorWrapper : LocationInterceptionAspect, IInstanceScopedAspect
{
public override void OnGetValue(LocationInterceptionArgs args)
{
if (args.LocationName == "Type")
{
args.Value = "computed value here";
}
args.ProceedGetValue();
}
[IntroduceMember(OverrideAction = MemberOverrideAction.OverrideOrFail)]
public String Type { get; set; }
I was also hoping there was a better way of doing this than overriding OnGetValue as that's called for each getter where really I want to only target the getter of the property that's been injected
Cheers
I am developing a Windows Phone 7 app and am using the MVVM pattern. I have a need to pass a parameter to the contructor of the ViewModel for a page. All my datacontexts and binding are done in XAML. Through my research I've seen that I need to do so using a dependency injector such as NInject.
Here's a little detail on whats going on:
I have a page with a ListPicker that lists various tasks. Each task has a unique TaskID. When an item is selected I need to open another page that will show the selected Tasks detail. My ViewModel and binding is all done and works if I use a static TaskID in the ViewModel but of course I need to use a variable.
I've setup NInject in the project and the various classes needed such as ViewModelLocator and my NInjectModule as shown here:
public class LighthouseNInjectModule : NinjectModule
{
public override void Load()
{
this.Bind<TaskViewModel>().ToSelf().WithConstructorArgument("TaskID", 2690);
}
}
Note that I have hardcoded a TaskID here and using this code this value properly gets injected into my constructor. Of course, this is hardcoded and I need to get the TaskID for the selected ListPicker item. I know how to get the selected ID from the ListPicker but how do I make NInject aware of it so when my class constructor is run it will have the correct value?
Here is the basic definition of my ViewModel class showing use of the Injector attribute.
public class TaskViewModel : INotifyPropertyChanged
{
[Inject]
public TaskViewModel(int TaskID)
{
//run function to get data using TaskID
}
}
WithConstructorArgument has another oveload that accepts a lazy evaluated Func<Context, object>.
I have a class which needs to use an IRepository for one method in it's class.
Ideally, I would like to avoid having to resolve this dependency into the class's constructor, and so I found method level injection in Ninject and was wondering how this works?
I understand how to set it up. What I'm confused about is how to call it?
Example:
class SomeClassThatUsesRepository
{
[Inject]
public void QueryForSomeStuff(IRepository repository)
{
//do some stuff
}
}
My problem is how do I call this method without specifying an IRepository?
var someClass = Kernel.Resolve<SomeClassThatUsesRepository>();
would work if I was using the constructor, but I want to call a method.
How do I call a method using Ninject method injection?
I'm afraid method injection doesn't work this way - it's just one of the ways to inject dependencies into an object during its construction (you can inject your dependencies through constructor parameters, through properties, fields or methods). Method injection is useful if your class takes its dependencies by Java-style setter methods like
public void SetRepository(IRepository repository) { ... }
If it is marked with [Inject] attribute, you don't need to call this methods directly, it is to be called by Ninject during the initialization to pass the IRepository object into your resolved object.
So I believe your QueryForSomeStuff method is being called when you resove your SomeClassThatUsesRepository.
Confirmed that method injection doesn't work as intended. Got a custom MVC attribute class and wanted to use an injected object inside it. Did not pass it
into the constructor and added method
[Ninject.Inject]
public void ResolveDI(ISettingStore store)
{
ConfigHelper = store;
}
This method was never called and ConfigHelper was null when the attribute's OnActionExecuting was called.