I'm trying out Unity and I'm having problems declaring my viewmodel in XAML. Can you help me out?
XAML:
<UserControl.DataContext>
<search:SearchBoxViewModel />
</UserControl.DataContext>
Constructor:
[ImportingConstructor]
public SearchBoxViewModel(IRegionManager regionManager, IEventAggregator eventAggregator)
{
this.regionManager = regionManager;
this.eventAggregator = eventAggregator;
}
When I try to execute I get a resolutionfailedexception.
This worked when the viewmodel had an empty constructor. It seems as if it's having problems with the constructor injection.
If I load the module like this:
var searchView = Container.Resolve<SearchBoxView>();
searchView.DataContext = Container.Resolve<SearchBoxViewModel>();
//RegionManager.RegisterViewWithRegion(RegionNames.SearchRegion, typeof(SearchBoxView));
RegionManager.Regions[RegionNames.SearchRegion].Add(searchView);
It works.
Is there any possibility to do this with xaml ( with I personally think is better )?
By the way: I'm creating an application with wpf that primarily communicates with a webservice. What should I rather user: unity or MEF and what are the big differences between the two?
Thanks,
Raphi
http://msdn.microsoft.com/en-us/library/ms753379.aspx:
Requirements for a Custom Class as a XAML Element
In order to be able to be instantiated as an object element, your
class must meet the following requirements:
Your custom class must be public and support a default
(parameterless)
public constructor. (See following section for notes regarding
structures.)
...
So, if you want to use dependencies, you should right something like:
var searchView = Container.Resolve<SearchBoxView>();
public class SearchBoxView: UserControl
{
[Dependency]
public SearchBoxViewModel ViewModel
{
get { return (SearchBoxViewModel)DataContext; }
set { DataContext = value; }
}
Related
I'm currently switching from .net framework to .net core 3.1.
Defining Api Controllers inside the namespace is all fine and works.
Now I have the case, that I need to declare the Api Controllers within another class, like this:
namespace Api.Controllers
{
public class MainClass : BaseClass
{
public MainClass()
{
}
[ApiController]
[Route("Test")]
public class TestController : ControllerBase
{
[HttpGet]
public int GetResult()
{
return 0;
}
}
}
}
The result is, that the Api Controller can't be found after calling the "AddControllers" method inside the "ConfigureServices" method of the startup class.
The MainClass is instantiated before the Startup class will be called.
I've tried to change the global route and defining an area like "{area=Test}/{controller=Test}", or set the ApiController attribute above the MainClass, but none of them worked.
Is there a way to get this working?
Looks like the default ControllerFeatureProvider does not treat nested controller types as controller. You can add (don't need to replace) your custom provider to change that behavior, like this:
public class NestedControllerFeatureProvider : ControllerFeatureProvider
{
protected override bool IsController(TypeInfo typeInfo)
{
if(!typeInfo.IsClass) return false;
if(typeInfo.IsAbstract) return false;
var isNestedType = typeInfo.DeclaringType != null;
var isPublic = true;
var parentType = typeInfo.DeclaringType;
while(parentType != null){
isPublic = parentType.IsPublic;
parentType = parentType.DeclaringType;
}
return isNestedType && isPublic;
}
}
Then add that provider to the ApplicationPartManager in Startup.ConfigureServices like this:
services
.AddMvc()
.ConfigureApplicationPartManager(appPart => {
appPart.FeatureProviders.Add(new NestedControllerFeatureProvider());
});
If you want to replace the default ControllerFeatureProvider, just find it in the FeatureProviders and remove it. Of course then you need to ensure that your custom one should handle everything just like what done by the default logic, something like this:
//for IsController
return base.IsController(typeInfo) || <...your-custom-logic...>;
NOTE: You can refer to the default implementation of ControllerFeatureProvider to learn some standard logic to implement your own logic correctly. The code above is just a basic example. To me, as long as the classes inherits from ControllerBase and not abstract, they can work fine as a controller to serve requests. There would be no serious troubles except some weird conventions (e.g: class name not ending with Controller is still a controller or some standard attributes applied on the controller class are not working ...).
We should not use nested controller classes. Each controller class should be put in a separate file (as a good practice). However the point of this answer (the most interesting part that I'm pretty sure not many know about, is the use of ControllerFeatureProvider which can help you customize the features set in other scenarios). And really if you really have to stick with your design somehow, you of course have to use this solution, no other way.
In a Sitecore project I've integrated Simple Injector using this article
It uses sitecore pipelines and then uses a method in App_start
namespace BBC.App_Start
{
public class SimpleInjector : IPackage
{
public void RegisterServices(Container container)
{
GetContainer.RegisterServices(container);
container.Register(() => new SitecoreContext(), Lifestyle.Scoped);
container.Register(() => new Container(), Lifestyle.Singleton);
}
}
}
Simply I can inject container into controller constructor but can't have container in View files.
I tried to declare a static property in App-start and save container to it. but still I'm getting no registration type in Views
What is the best way to have container object in views?
As Stephen suggests in his comment, the literal answer to your question is "you shouldn't do that - because it's not really the way MVC and DI are supposed to work". The more detailed answer goes something like this:
The job of your view is to present data that it has been passed via the Model. Views should not really contain logic. Very simple stuff like "if flag is false, hide this block of mark-up" is ok, but the more complex code to work out what the value of the flag is shouldn't be in the view.
MVC tries to make our website code better by encouraging you to separate presentation (the View) from data (the Model) and logic (the Controller). This should make our code easier to work with - So if you have processing that needs doing, then it should really be happening when your controller method runs.
If your view requires some special data, best practice suggests it should work it out in the controller method and pass it to the view in the model. The code might look more like this:
public class MyModel
{
public string SpecialData { get; set; }
}
public class MyController : Controller
{
public ActionResult DoSomething()
{
// do whatever processing is needed
var somethingCalculate = resultFromYourOtherObject();
// do other stuff
var model = new MyModel() { SpecialData = somethingCalculated };
return View(model);
}
}
And then the View just needs to accept the MyModel class as its model, and render the SpecialData property - no logic required.
I think also it's considered a bad idea to have calls to fetch objects from your DI container spread about your codebase. For MVC apps, generally your DI container gets wired in to the process of creating a controller for a request when the app starts up. Rather than passing about a DI Container into your controllers, the DI framework extends the Controller-creation process, and the container isn't exposed outside of this. When the MVC runtime needs to create a controller, the controller-creation logic uses the DI framework to fetch objects for all the controller's dependencies.
Without more detail about what you actually want to achieve, it's difficult to say what the "right" approach to creating your object(s) here is, but the two most common patterns are probably:
1) Constructor injection: Your controller has a parameter which accepts the object required. The DI container creates this object for you at the point where it creates the controller, so your controller gets all its dependencies when it is created. Good for: scenarios where you know how to create the object at the beginning of the request.
public interface IMySpecialObject
{
string DoSomething();
}
public class MyController : Controller
{
private IMySpecialObject _specialObject;
public MyController(IMySpecialObject specialObject)
{
_specialObject = specialObject;
}
public ActionResult RenderAView()
{
// do some stuff
var data = _specialObject.DoSomething();
return View(data);
}
}
As long as IMySpecialObject and a concrete implementation for it are registered with your DI container when your app starts up, all is well.
2) Factory classes: Sometimes, however, the object in question might be optional, or it might require data that's not available at controller-creation time to create it. In that case, your DI framework could pass in a Factory object to your controller, and this is used to do the construction of the special object later.
public interface ISpecialFactory
{
ISpecialObject CreateSpecialObject(object data);
}
public class MyController : Controller
{
private IMySpecialFactory _specialFactory;
public MyController(IMySpecialFactory specialFactory)
{
_specialFactory = specialFactory;
}
public ActionResult RenderAView()
{
// do some stuff
if( requireSpecialObject )
{
var data = getSomeData();
var specialObject = _specialFactory.CreateSpecialObject(data);
var data = _specialObject.DoSomething();
return View(data);
}
return View("someOtherView");
}
}
But a good book on using DI may suggest other approaches that fit your specific problem better.
The inital problem is coming from a personal project about the polyline of the Xamarin.Forms.Map where the initialization is realized by a binding from the XAML part..
Let me be clear by an example :
I have an object CustomMap.cs which inherit from Xamarin.Forms.Map (This file is in the PCL part -> CustomControl/CustomMap.cs)
public class CustomMap : Map, INotifyPropertyChanged
{
public static readonly BindableProperty PolylineAddressPointsProperty =
BindableProperty.Create(nameof(PolylineAddressPoints), typeof(List<string>), typeof(CustomMap), null);
public List<string> PolylineAddressPoints
{
get { return (List<string>)GetValue(PolylineAddressPointsProperty); }
set
{
SetValue(PolylineAddressPointsProperty, value);
this.GeneratePolylineCoordinatesInner();
}
}
// ...
}
As you can see, I have a bindable property with an assessor and the XAML doesn't seem to use this assessor..
So the MainPge.xaml part of the page, where the control is called, looks like that:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:control="clr-namespace:MapPolylineProject.CustomControl;assembly=MapPolylineProject"
x:Class="MapPolylineProject.Page.MainPage">
<ContentPage.Content>
<control:CustomMap x:Name="MapTest" PolylineAddressPoints="{Binding AddressPointList}"
VerticalOptions="Fill" HorizontalOptions="Fill"/>
</ContentPage.Content>
</ContentPage>
The MainPge.xaml.cs part:
public partial class MainPage : ContentPage
{
public List<string> AddressPointList { get; set; }
public MainPage()
{
base.BindingContext = this;
AddressPointList = new List<string>()
{
"72230 Ruaudin, France",
"72100 Le Mans, France",
"77500 Chelles, France"
};
InitializeComponent();
//MapTest.PolylineAddressPoints = AddressPointList;
}
}
So, everything is fine if I edit the PolylineAddressPoints from the object instance (if the commented part isnt' commented..), but if I init the value from the XAML (from the InitializeComponent();), it doesn't work, the SetValue, in the Set {}, of the CustomMap.PolylineAddressPoints, isn't called..
I then searched on the web about it and get something about the Dependency Properties? or something like that. So I tried some solutions but, from WPF, so some methods, such as DependencyProperty.Register();. So yeah, I can't find the way to solve my problem..
I also though about something, if DependencyProperty.Register(); would exists in Xamarin.Forms, then it means I would have to do it for each values? Because, if every value has to be set by a XAML binding logic, it would not work, I would have to register every value, doesn't it?
I'm sorry if I'm not clear, but I'm so lost about this problem.. Please, do not hesitate to ask for more details, thank in advance !
Finaly, the initial problem is that I'm trying to set a value of an object/control, from the XAML. Doing this by a Binding doesn't work, it seems like it ignored.. However, it does work if I do the following:
MapTest.PolylineAddressPoints = AddressPointList;
There are multiple questions in this:
Why is the property setter never called when using Xaml ?
Am I properly defining my BindableProperty ?
Why is my binding failing ?
Let me answer them in a different order.
Am I properly defining my BindableProperty ?
The BindableProperty declaration is right, but could be improved by using an IList<string>:
public static readonly BindableProperty PolylineAddressPointsProperty =
BindableProperty.Create(nameof(PolylineAddressPoints), typeof(IList<string>), typeof(CustomMap), null);
but the property accessor is wrong, and should only contains this:
public IList<string> PolylineAddressPoints
{
get { return (IList<string>)GetValue(PolylineAddressPointsProperty); }
set { SetValue(PolylineAddressPointsProperty, value); }
}
I'll tell you why while answering the next question. But you want to invoke a method when the property has changed. In order to do that, you have to reference a propertyChanged delegate to CreateBindableProperty, like this:
public static readonly BindableProperty PolylineAddressPointsProperty =
BindableProperty.Create(nameof(PolylineAddressPoints), typeof(IList<string>), typeof(CustomMap), null,
propertyChanged: OnPolyLineAddressPointsPropertyChanged);
And you have to declare that method too:
static void OnPolyLineAddressPointsPropertyChanged(BindableObject bindable, object oldValue, object newValue)
{
((CustomMap)bindable).OnPolyLineAddressPointsPropertyChanged((IList<string>)oldValue, (IList<string>)newValue);
}
void OnPolyLineAddressPointsPropertyChanged(IList<string> oldValue, IList<string> newValue)
{
GeneratePolylineCoordinatesInner();
}
Why is the property setter never called when using Xaml ?
The property, and the property accessors, are only meant to be invoked when accessing the property by code. C# code.
When setting a property with a BindablePrperty backing store from Xaml, the property accessors are bypassed and SetValue() is used directly.
When defining a Binding, both from code or from Xaml, property accessors are again bypassed and SetValue() is used when the property needs to be modified. And when SetValue() is invoked, the propertyChanged delegate is executed after the property has changed (to be complete here, propertyChanging is invoked before the property change).
You might wonder why bother defining the property if the bindable property is only used by xaml, or used in the context of Binding. Well, I said the property accessors weren't invoked, but they are used in the context of Xaml and XamlC:
a [TypeConverter] attribute can be defined on the property, and will be used
with XamlC on, the property signature can be used to infer, at compile time, the Type of the BindableProperty.
So it's a good habit to always declare property accessors for public BindableProperties. ALWAYS.
Why is my binding failing ?
As you're using CustomMap as both View and ViewModel (I won't tell the Mvvm Police), doing this in your constructor should be enough:
BindingContext = this; //no need to prefix it with base.
As you're doing it already, your Binding should work once you've modified the BindableProperty declaration in the way I explained earlier.
I just recently started using Ninject (v2.2.0.0) in my ASP.NET MVC 3 application. So far I'm thrilled with it, but I ran into a situation I can't seem to figure out.
What I'd like to do is bind an interface to concrete implementations and have Ninject be able to inject the concrete implementation into a constructor using a factory (that will also be registered with Ninject). The problem is that I'd like my constructor to reference the concrete type, not the interface.
Here is an example:
public class SomeInterfaceFactory<T> where T: ISomeInterface, new()
{
public T CreateInstance()
{
// Activation and initialization logic here
}
}
public interface ISomeInterface
{
}
public class SomeImplementationA : ISomeInterface
{
public string PropertyA { get; set; }
}
public class SomeImplementationB : ISomeInterface
{
public string PropertyB { get; set; }
}
public class Foo
{
public Foo(SomeImplementationA implA)
{
Console.WriteLine(implA.PropertyA);
}
}
public class Bar
{
public Bar(SomeImplementationB implB)
{
Console.WriteLine(implB.PropertyB);
}
}
Elsewhere, I'd like to bind using just the interface:
kernel.Bind<Foo>().ToSelf();
kernel.Bind<Bar>().ToSelf();
kernel.Bind(typeof(SomeInterfaceFactory<>)).ToSelf();
kernel.Bind<ISomeInterface>().To ...something that will create and use the factory
Then, when requesting an instance of Foo from Ninject, it would see that one of the constructors parameters implements a bound interface, fetch the factory, and instantiate the correct concrete type (SomeImplementationA) and pass it to Foo's constructor.
The reason behind this is that I will have many implementations of ISomeInterface and I'd prefer to avoid having to bind each one individually. Some of these implementations may not be known at compile time.
I tried using:
kernel.Bind<ISomeInterface>().ToProvider<SomeProvider>();
The provider retrieves the factory based on the requested service type then calls its CreateInstance method, returning the concrete type:
public class SomeProvider : Provider<ISomeInterface>
{
protected override ISomeInterface CreateInstance(IContext context)
{
var factory = context.Kernel.Get(typeof(SomeInterfaceFactory<>)
.MakeGenericType(context.Request.Service));
var method = factory.GetType().GetMethod("CreateInstance");
return (ISomeInterface)method.Invoke();
}
}
However, my provider was never invoked.
I'm curious if Ninject can support this situation and, if so, how I might go about solving this problem.
I hope this is enough information to explain my situation. Please let me know if I should elaborate further.
Thank you!
It seems you have misunderstood how ninject works. In case you create Foo it sees that it requires a SomeImplementationA and will try to create an instance for it. So you need to define a binding for SomeImplementationA and not for ISomeInterface.
Also most likely your implementation breaks the Dependency Inversion Princple because you rely upon concrete instances instead of abstractions.
The solution to register all similar types at once (and the prefered way to configure IoC containers) is to use configuration by conventions. See the Ninject.Extensions.Conventions extenstion.
I'm working on a framework extension which handles dynamic injection using Ninject as the IoC container, but I'm having some trouble trying to work out how to achieve this.
The expectation of my framework is that you'll pass in the IModule(s) so it can easily be used in MVC, WebForms, etc. So I have the class structured like this:
public class NinjectFactory : IFactory, IDisposable {
readonly IKernel kernel;
public NinjectFactory(IModule[] modules) {
kernel = new StandardKernel(modules);
}
}
This is fine, I can create an instance in a Unit Test and pass in a basic implementation of IModule (using the build in InlineModule which seems to be recommended for testing).
The problem is that it's not until runtime that I know the type(s) I need to inject, and they are requested through the framework I'm extending, in a method like this:
public IInterface Create(Type neededType) {
}
And here's where I'm stumped, I'm not sure the best way to check->create (if required)->return, I have this so far:
public IInterface Create(Type neededType) {
if(!kernel.Components.Has(neededType)) {
kernel.Components.Connect(neededType, new StandardBindingFactory());
}
}
This adds it to the components collection, but I can't work out if it's created an instance or how I create an instance and pass in arguments for the .ctor.
Am I going about this the right way, or is Ninject not even meant to be be used that way?
Unless you want to alter or extend the internals of Ninject, you don't need to add anything to the Components collection on the kernel. To determine if a binding is available for a type, you can do something like this:
Type neededType = ...;
IKernel kernel = ...;
var registry = kernel.Components.Get<IBindingRegistry>();
if (registry.Has(neededType)) {
// Ninject can activate the type
}
Very very late answer but Microsoft.Practices.Unity allows Late Binding via App.Config
Just in case someone comes across this question