I'm implementing a finite-state machine, with each class representing a state. Each state knows which other states it can transition to, and this naturally leads to circular relationships. (See the State Design Pattern).
For this simplified example I'm creating two components, where the first component has a reference to the second component, and the second component has a reference to the first.
The problem is that the Windsor framework is correctly setting the references for the first created component, but not setting the references for the second:
Here are the two components:
// DefaultMouseHandler knows about NewLineMouseHandler
public class DefaultMouseHandler : MouseHandler
{
public DefaultMouseHandler()
{
}
public NewLineMouseHandler NewLineMouseHandler
{
get;
set;
}
internal override MouseHandler LeftButtonDown(System.Windows.Input.MouseButtonEventArgs e)
{
return this.NewLineMouseHandler;
}
}
// NewLineMouseHandler knows about DefaultMouseHandler
public class NewLineMouseHandler : MouseHandler
{
public NewLineMouseHandler()
{
}
public DefaultMouseHandler DefaultMouseHandler
{
get;
set;
}
internal override MouseHandler LeftButtonUp(System.Windows.Input.MouseButtonEventArgs e)
{
return this.DefaultMouseHandler;
}
}
I then register the components as so:
_windsorContainer.Register(Classes.FromThisAssembly()
.BasedOn<MouseHandler>()
);
But when I first attempt to create the DefaultMouseHandler:
The DefaultMouseHandler is constructed
The NewLineMouseHandler is constructed
The NewLineMouseHandler is set on the DefaultMouseHandler
But the DefaultMouseHandler is NOT set on the NewLineMouseHandler.
Can this be considered a defect in Castle Windsor?
What's the best way to have the two components referencing each other, without either component being aware of the Windsor container?
I agree with #sll that it might be a sign the design could be improved. On the other hand there are valid reasons for doing what you're doing. If you never resolve NewLineMouseHandler and it's only used as dependency of NewLineMouseHandler, just set the dependency manually:
windsor.Register(Classes.FromThisAssembly()
.BasedOn<MouseHandler>()
.ConfigureFor<NewLineMouseHandler>(
h => h.OnCreate(
c =>
{
var #default = (DefaultMouseHandler) c;
#default.NewLineMouseHandler.DefaultMouseHandler = #default;
}))
);
The solution I've come up with is to use the TypedFactoryFacility.
This allows objects to be created as they are needed, so we don't have the complications of them all being dependent upon one another at initialization time.
public interface IMouseHandlerFactory
{
T CreateHandler<T>() where T : MouseHandler;
}
// In the registration code
_windsorContainer.AddFacility<TypedFactoryFacility>();
_windsorContainer.Register(Classes.FromThisAssembly()
.BasedOn<MouseHandler>(),
Component.For<IMouseHandlerFactory>()
.AsFactory()
);
// The base class
public abstract class MouseHandler
{
// Every mousehandler will create at least one other mouse handler
// This is the factory that they will use for mouse handling creation
// The property will be automatically set by the DI container
public IMouseHandlerFactory MouseHandlerFactory { get; set; }
// Methods the concrete implementations will override
internal virtual MouseHandler LeftButtonDown(MouseButtonEventArgs e) { return this; }
internal virtual MouseHandler LeftButtonUp(MouseButtonEventArgs e) { return this; }
}
// The implementations
public class DefaultMouseHandler : MouseHandler
{
internal override MouseHandler LeftButtonDown(MouseButtonEventArgs e)
{
return this.MouseHandlerFactory.CreateHandler<NewLineMouseHandler>();
}
}
public class NewLineMouseHandler : MouseHandler
{
internal override MouseHandler LeftButtonUp(MouseButtonEventArgs e)
{
return this.MouseHandlerFactory.CreateHandler<DefaultMouseHandler>();
}
}
Related
I want to register an interface like: IInterceptingAware, so that for all classes which implement this interface an interceptor class is used.
public class InterceptorClass : IInterceptor
{
public void Intercept(IInvocation invocation)
{
// Do my work
}
}
public class Foo : IInterceptingAware
{
}
public class Bar : IInterceptingAware
{
}
How do I setup castle windsor for this?
using (var container = new WindsorContainer())
{
container.Register(
Component.For<MyInterceptorClass>(),
Classes.FromThisAssembly()
.BasedOn<IInterceptingAware>()
.WithServiceDefaultInterfaces()
.ConfigureFor<IInterceptingAware>(c => c.Interceptors<MyInterceptorClass>())
);
var foo = container.Resolve<Foo>();
foo.Test();
var bar = container.Resolve<IBar>();
bar.Test();
}
Console.ReadLine();
Keep in mind interceptor requires at least virtual methods on target class, even better your target class should implement an interface in order to have the interceptor working on that contract.
Said so, your Foo class should at least have a method named Test marked as virtual
while Bar should implement IBar:
public interface IBar
{
void Test();
}
in a main viewmodel where i collect data from another viewmodels, I created in summary two or three public Init methods with different signatures. When i navigate back to the base viewmodel from the other viewmodels with ShowViewModel, I awaited that the right Init method will be executed, but this don't happen. Regarding the greet practical documentation here:
http://slodge.blogspot.ch/2013/03/v3-new-viewmodel-lifecycle.html
This should be work :-/.
I will explain this with some code.
My main view model is e.g.:
public class MainViewModel : MvxViewModel
{
MainViewModel() {}
public class ParameterFirst
{
public string Id { get; set; }
}
public class ParameterSecond
{
public string Id { get; set; }
}
public class ParameterSecond
{
public string Id { get; set; }
}
public class ParameterThird
{
public string Id { get; set; }
}
public void Init(ParameterFirst objFirst)
{
//do something
}
public void Init(ParameterSecond objSecond)
{
//do something
}
public void Init(ParameterThird objThird)
{
//do something
}
}
Then I will navigate from another viewmodel and await that the right Init method will be executed:
public class CollectData_ONE_ViewModel : MvxViewModel
{
CollectData_ONE_ViewModel() {}
public void DidWork()
{
//Hopefully the Init method with argument ParameterFirst should be called
base.ShowViewModel<MainViewModel>(new MainViewModel.ParameterFirst { Id = "11" });
}
}
next here the second viewmodel
public class CollectData_SECOND_ViewModel : MvxViewModel
{
CollectData_SECOND_ViewModel() {}
public void DidWork()
{
//Hopefully the Init method with argument ParameterFirst should be called
base.ShowViewModel<MainViewModel>(new MainViewModel.ParameterSecond { Id = "22" });
}
}
and the third viewmodel
public class CollectData_THIRD_ViewModel : MvxViewModel
{
CollectData_THIRD_ViewModel() {}
public void DidWork()
{
//Hopefully the Init method with argument ParameterFirst should be called
base.ShowViewModel<MainViewModel>(new MainViewModel.ParameterThird { Id = "33" });
}
}
In my code, each time the First Init method is called, I'm really at the end and don't have further ideas :) Did anyone here experienced the same issue? Or do anyone here have another Idea to collect data to the main viewmodel in an elegant way? Thanks a lot in advance for reading :)
The Init mechanism in MvvmCross is deliberately lightweight. If you declare multiple methods, all of them will be called - this is by design. Also if some of the Init parameter objects were to share properties then these would clash - see Custom types in Navigation parameters in v3
As it says in the blog post you reference "generally you will probably only want to use one within your application" - so I'd recommend refactoring to a single navigation parameter object and using your own ViewModel-based logic to decide how your ViewModel should initialise.
If you really do need three Init methods called in three different situations, then you can easily pack and unpack your own parameter objects using a custom method (possibly in a BaseViewModel class) like in https://stackoverflow.com/a/19059938/373321
While trying to coerce Windsor into wrapping an implementation with a random number of decorators, i've stumbled upon the following:
i have 3 decorators and an implementation all using the same interface.
if you run this code, windsor resolves icommandhandler<stringcommand> as implementation, which, as far as i can tell, is expected behaviour, because the typed implementation can not be registered with the open typed decorators.
However, if you uncomment the line container.Register(Component.For<ICommandHandler<stringCommand>>().ImplementedBy<Decorator1<stringCommand>>());, all three decorators will be used to resolve implementation, which is the desired result (sort of : ).
class Program
{
static void Main(string[] args)
{
var container = new WindsorContainer();
container.Register(Component.For(typeof(ICommandHandler<>)).ImplementedBy(typeof(Decorator1<>)));
container.Register(Component.For(typeof(ICommandHandler<>)).ImplementedBy(typeof(Decorator2<>)));
container.Register(Component.For(typeof(ICommandHandler<>)).ImplementedBy(typeof(Decorator3<>)));
//uncomment the line below and watch the magic happen
//container.Register(Component.For<ICommandHandler<stringCommand>>().ImplementedBy<Decorator1<stringCommand>>());
container.Register(Component.For<ICommandHandler<stringCommand>>().ImplementedBy<implementation>());
var stringCommandHandler = container.Resolve<ICommandHandler<stringCommand>>();
var command = new stringCommand();
stringCommandHandler.Handle(command);
Console.WriteLine(command.s);
Console.ReadKey();
}
}
public interface ICommandHandler<T>
{
void Handle(T t);
}
public class stringCommand
{
public string s { get; set; }
}
public abstract class Decorator<T> : ICommandHandler<T>
{
public abstract void Handle(T t);
};
public class Decorator1<T> : Decorator<T>
where T : stringCommand
{
private ICommandHandler<T> _handler;
public Decorator1(ICommandHandler<T> handler)
{
_handler = handler;
}
public override void Handle(T t)
{
t.s += "Decorator1;";
_handler.Handle(t);
}
}
public class Decorator2<T> : Decorator<T>
where T : stringCommand
{
private ICommandHandler<T> _handler;
public Decorator2(ICommandHandler<T> handler)
{
_handler = handler;
}
public override void Handle(T t)
{
t.s += "Decorator2;";
_handler.Handle(t);
}
}
public class Decorator3<T> : Decorator<T>
where T : stringCommand
{
private ICommandHandler<T> _handler;
public Decorator3(ICommandHandler<T> handler)
{
_handler = handler;
}
public override void Handle(T t)
{
t.s += "Decorator3;";
_handler.Handle(t);
}
}
public class implementation : ICommandHandler<stringCommand>
{
public void Handle(stringCommand t)
{
t.s += "implementation;";
}
}
Why exactly is this happening, is this a feature of windsor that i am not aware of? Is there perhaps a different way to achieve the same effect? (without resorting to reflection)
When windsor tries to resolve a component it will first try to resolve the more specific interface. So when you register Component.For it will prefer to resolve this over an open generic type.
If the same interface is registered multiple times, it will use the first one specified.
So if you don't uncommment the line your application will resolve implementation since this is the most specific component.
If you do uncomment the line decorator1 will be resolved and indeed the magic starts. The decorator will now start looking for the first registered component that satisfies it's constructor, in this case that would be decorator1 again (you did notice that your output show decorator1 2 times ?). Which will the resolve the next registered component and so on till it comes to the actual implementation.
So the only thing I can think about is not registering decorator1 as an open generic but as a specific type.
Kind regards,
Marwijn.
I have two components registered for a service:
container.Register(
Component.For<IDataStorage>().Named("FirstChoice").ImplementedBy...
Component.For<IDataStorage>().Named("SecondChoice").ImplementedBy
Then I have a set of components deriving from this base class, that depends on those components:
public abstract class BaseMessageHandler
{
public IDataStorage FirstStorage {get; set;}
public IDataStorage SecondStorage {get; set;}
}
If I was registering these "handlers" (deriving from BaseMessageHandler) manually, I would specify a service override, indicating which component I want for properties "FirstStorage" and "SecondStorage". Something like:
.Configure(x => x.DependsOn(
ServiceOverride.ForKey("FirstStorage").Eq("FirstChoice"),
ServiceOverride.ForKey("SecondStorage").Eq("SecondChoice"))
Unfortunately, this registration is done automatically by a framework (NServiceBus). I know that if I register the handlers first (before NServiceBus has a chance to do so), these registrations will stick. But rather than try to guess and mimick the registration NServiceBus does, I wonder if I can specify service overrides in a custom IContributeComponentModelConstruction.
It seems a good place to do so, and I'm able to find these properties:
public class DataStorageOverrideContributor : IContributeComponentModelConstruction
{
public void ProcessModel(Castle.MicroKernel.IKernel kernel, Castle.Core.ComponentModel model)
{
var dataStorageDependencies = model.Properties.Where(
x => x.Dependency.TargetItemType == typeof(IDataStorage));
foreach (var propertyDependency in dataStorageDependencies)
{
// now what??
but I'm not sure the proper way to:
check if a service override is already specified (in which case I would do nothing)
add a service override to a property dependency.
Is this something that could be done inspecting and working the ComponentModel in the IContributeComponentModelConstruction.ProcessModel method?
I would use a subdependency resolver in your scenario. You can see the code below on how to use it.
Goodluck,
Marwijn.
public interface IDataStorage
{
}
public class DataStore1 : IDataStorage
{
}
public class DataStore2 : IDataStorage
{
}
public class BaseMessageHandler
{
public IDataStorage FirstStorage { get; set; }
public IDataStorage SecondStorage { get; set; }
}
public class SubDependencyResolver : ISubDependencyResolver
{
private readonly IKernel _kernel;
public SubDependencyResolver(IKernel kernel)
{
_kernel = kernel;
}
public bool CanResolve(CreationContext context, ISubDependencyResolver contextHandlerResolver, ComponentModel model,
DependencyModel dependency)
{
return model.Implementation == typeof (BaseMessageHandler) && dependency.TargetType == typeof(IDataStorage);
}
public object Resolve(CreationContext context, ISubDependencyResolver contextHandlerResolver, ComponentModel model,
DependencyModel dependency)
{
var handlers = _kernel.GetHandlers(dependency.TargetType);
switch (dependency.DependencyKey)
{
case "FirstStorage":
return handlers.Single(h => h.ComponentModel.Implementation == typeof (DataStore1)).Resolve(context);
case "SecondStorage":
return handlers.Single(h => h.ComponentModel.Implementation == typeof(DataStore2)).Resolve(context);
}
return null;
}
}
[TestFixture]
public class Tests
{
[Test]
public void SomeTest()
{
var container = new WindsorContainer();
container.Kernel.Resolver.AddSubResolver(new SubDependencyResolver(container.Kernel));
container.Register(
Component.For<IDataStorage>().Named("FirstChoice").ImplementedBy<DataStore1>(),
Component.For<IDataStorage>().Named("SecondChoice").ImplementedBy<DataStore2>(),
Component.For<BaseMessageHandler>()
);
var messageHandler = container.Resolve<BaseMessageHandler>();
Assert.AreEqual(typeof(DataStore1), messageHandler.FirstStorage.GetType());
Assert.AreEqual(typeof(DataStore2), messageHandler.SecondStorage.GetType());
}
}
alternative you may use:
case "FirstStorage":
return handlers.Single(h => h.ComponentModel.Name == "FirstChoice").Resolve(context);
case "SecondStorage":
return handlers.Single(h => h.ComponentModel.Name == "SecondChoice").Resolve(context);
to resolve on component name rather then implementation type.
I have an MVVM Cross application running on Windows Phone 8 which I recently ported across to using Portable Class Libraries.
The view models are within the portable class library and one of them exposes a property which enables and disables a PerformanceProgressBar from the Silverlight for WP toolkit through data binding.
When the user presses a button a RelayCommand kicks off a background process which sets the property to true which should enable the progress bar and does the background processing.
Before I ported it to a PCL I was able to invoke the change from the UI thread to ensure the progress bar got enabled, but the Dispatcher object isn't available in a PCL. How can I work around this?
Thanks
Dan
All the MvvmCross platforms require that UI-actions get marshalled back on to the UI Thread/Apartment - but each platform does this differently....
To work around this, MvvmCross provides a cross-platform way to do this - using an IMvxViewDispatcherProvider injected object.
For example, on WindowsPhone IMvxViewDispatcherProvider is provided ultimately by MvxMainThreadDispatcher in https://github.com/slodge/MvvmCross/blob/vnext/Cirrious/Cirrious.MvvmCross.WindowsPhone/Views/MvxMainThreadDispatcher.cs
This implements the InvokeOnMainThread using:
private bool InvokeOrBeginInvoke(Action action)
{
if (_uiDispatcher.CheckAccess())
action();
else
_uiDispatcher.BeginInvoke(action);
return true;
}
For code in ViewModels:
your ViewModel inherits from MvxViewModel
the MvxViewModel inherits from an MvxApplicationObject
the MvxApplicationObject inherits from an MvxNotifyPropertyChanged
the MvxNotifyPropertyChanged object inherits from an MvxMainThreadDispatchingObject
MvxMainThreadDispatchingObject is https://github.com/slodge/MvvmCross/blob/vnext/Cirrious/Cirrious.MvvmCross/ViewModels/MvxMainThreadDispatchingObject.cs
public abstract class MvxMainThreadDispatchingObject
: IMvxServiceConsumer<IMvxViewDispatcherProvider>
{
protected IMvxViewDispatcher ViewDispatcher
{
get { return this.GetService().Dispatcher; }
}
protected void InvokeOnMainThread(Action action)
{
if (ViewDispatcher != null)
ViewDispatcher.RequestMainThreadAction(action);
}
}
So... your ViewModel can just call InvokeOnMainThread(() => DoStuff());
One further point to note is that MvvmCross automatically does UI thread conversions for property updates which are signalled in a MvxViewModel (or indeed in any MvxNotifyPropertyChanged object) through the RaisePropertyChanged() methods - see:
protected void RaisePropertyChanged(string whichProperty)
{
// check for subscription before going multithreaded
if (PropertyChanged == null)
return;
InvokeOnMainThread(
() =>
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(whichProperty));
});
}
in https://github.com/slodge/MvvmCross/blob/vnext/Cirrious/Cirrious.MvvmCross/ViewModels/MvxNotifyPropertyChanged.cs
This automatic marshalling of RaisePropertyChanged() calls works well for most situations, but can be a bit inefficient if you Raise a lot of changed properties from a background thread - it can lead to a lot of thread context switching. It's not something you need to be aware of in most of your code - but if you ever do find it is a problem, then it can help to change code like:
MyProperty1 = newValue1;
MyProperty2 = newValue2;
// ...
MyProperty10 = newValue10;
to:
InvokeOnMainThread(() => {
MyProperty1 = newValue1;
MyProperty2 = newValue2;
// ...
MyProperty10 = newValue10;
});
If you ever use ObservableCollection, then please note that MvvmCross does not do any thread marshalling for the INotifyPropertyChanged or INotifyCollectionChanged events fired by these classes - so it's up to you as a developer to marshall these changes.
The reason: ObservableCollection exists in the MS and Mono code bases - so there is no easy way that MvvmCross can change these existing implementations.
If you don't have access to the Dispatcher, you can just pass a delegate of the BeginInvoke method to your class:
public class YourViewModel
{
public YourViewModel(Action<Action> beginInvoke)
{
this.BeginInvoke = beginInvoke;
}
protected Action<Action> BeginInvoke { get; private set; }
private void SomeMethod()
{
this.BeginInvoke(() => DoSomething());
}
}
Then to instanciate it (from a class that has access to the dispatcher):
var dispatcherDelegate = action => Dispatcher.BeginInvoke(action);
var viewModel = new YourViewModel(dispatcherDelegate);
Or you can also create a wrapper around your dispatcher.
First, define a IDispatcher interface in your portable class library:
public interface IDispatcher
{
void BeginInvoke(Action action);
}
Then, in the project who has access to the dispatcher, implement the interface:
public class DispatcherWrapper : IDispatcher
{
public DispatcherWrapper(Dispatcher dispatcher)
{
this.Dispatcher = dispatcher;
}
protected Dispatcher Dispatcher { get; private set; }
public void BeginInvoke(Action action)
{
this.Dispatcher.BeginInvoke(action);
}
}
Then you can just pass this object as a IDispatcher instance to your portable class library.
Another option that could be easier is to store a reference to SynchronizationContext.Current in your class's constructor. Then, later on, you can use _context.Post(() => ...) to invoke on the context -- which is the UI thread in WPF/WinRT/SL.
class MyViewModel
{
private readonly SynchronizationContext _context;
public MyViewModel()
{
_context = SynchronizationContext.Current.
}
private void MyCallbackOnAnotherThread()
{
_context.Post(() => UpdateTheUi());
}
}