Castle Windsor: Register by convention, open generics - castle-windsor

I have an interface like so:
public interface IGenericRepository<T>
I have a base class like so:
public abstract class GenericRepository<T> : IGenericRepository<T> where T : class
I have a class like so:
public class AGenericRepository<T> : GenericRepository<T> where T : class
Without convention, I successfully registered like so:
container.Register(
Component.For(typeof(GenericRepository<>)).ImplementedBy(typeof(AGenericRepository<>))
);
I can successfully resolve an object like so:
var robot = container.Resolve<GenericRepository<Android>>();
However, when trying to register by convention like so:
container.Register(Classes.FromThisAssembly()
.BasedOn(typeof(GenericRepository<>))
.WithService.Base());
I cannot resolve as I did above. What gives?

Writing an answer since this may be too long (and codeful) for a comment.
Given the following code:
public interface IGenericRepository<T> {}
public abstract class GenericRepository<T> : IGenericRepository<T> where T : class {}
public class AGenericRepository<T> : GenericRepository<T> where T : class {}
public class AInstance: AGenericRepository<string>{}
this registration works fine for me:
var container = new WindsorContainer();
container.Register(Classes.FromThisAssembly().BasedOn(typeof (GenericRepository<>)).WithServiceBase());
var result = container.Resolve<GenericRepository<string>>();
I have a feeling that we are lacking some information regarding what classes are registered.
EDIT: in the proposed code apparently the abstract base class acts as a stop gap to determine what the base service is. If you use the following registration the resolution works:
var container = new WindsorContainer();
container.Register(Classes.FromThisAssembly().BasedOn(typeof (GenericRepository<>)).WithServiceAllInterfaces());
var result = container.Resolve<IGenericRepository<string>>();
However the resolution against the GenericRepository doesn't seem to work because it is not registered as a resolution component in castle. If you want to self register components you can describe it directly:
var container = new WindsorContainer();
container.Register(Classes.FromThisAssembly().BasedOn(typeof (GenericRepository<>)).WithServices(typeof(GenericRepository<>)));
var result = container.Resolve<GenericRepository<string>>();
// result is AGenericRepository<string>

DefaultInterfaces() only registers interfaces with a matching name.
Matching names, means that the implementing class contains in its name
the name of the interface (without the I on the front).
http://docs.castleproject.org/Windsor.Registering-components-by-conventions.ashx

Related

Any alternative to injecting Castle Windsor typed factories?

Most of my components are registered using the code-based (fluent) approach, but there is one particular component that I need to resolve differently at runtime. This is the interface and a couple of concrete implementations:-
public interface ICommsService ...
public class SerialCommsService : ICommsService ...
public class TcpCommsService : ICommsService ...
Some of our users will need the serial service while others will need the TCP service. My current solution (which works btw) is to use a typed factory and a custom component selector - the latter reads an app.config setting to determine which implementation the typed factory will resolve and return.
First the typed factory (nothing special about this):-
public interface ICommsServiceFactory
{
ICommsService Create();
void Release(ICommsService component);
}
Next, the custom component selector, which reads the fully-qualified type name from app.config (e.g. "MyApp.SomeNamespace.TcpCommsService"):-
public class CommsFactoryComponentSelector : DefaultTypedFactoryComponentSelector
{
protected override string GetComponentName(MethodInfo method, object[] arguments)
{
return ConfigurationManager.AppSettings["commsServiceType"];
}
}
Then the registration stuff:-
var container = new WindsorContainer();
container.AddFacility<TypedFactoryFacility>();
container.Register(Component.For<ITypedFactoryComponentSelector>()
.ImplementedBy<CommsFactoryComponentSelector>());
container.Register(Component.For<ICommsFactory>()
.AsFactory(o => o.SelectedWith<CommsFactoryComponentSelector>()));
container.Register(Component.For<ICommsService>()
.ImplementedBy<SerialCommsService>().LifeStyle.Singleton);
container.Register(Component.For<ICommsService>()
.ImplementedBy<TcpCommsService>().LifeStyle.Singleton);
Finally, an example class with a dependency on ICommsService:-
public class Test
{
public Test(ICommsFactory commsFactory)
{
var commsService = commsFactory.Create();
...
}
}
As already mentioned, the above solution does work, but I don't like having to inject the factory. It would be more intuitive if I could just inject an ICommsService, and let something somewhere figure out which implementation to resolve and inject - similar to what I'm doing now but earlier in Windsor's "resolving pipeline". Is something like that possible?
You can use UsingFactoryMethod here:
container.Register(Component.For<ICommsService>().UsingFactoryMethod(kernel => kernel.Resolve<ICommsServiceFactory>().Create()));
You can inject ICommsService to any class now. ICommsServiceFactory can be a simple interface now:
interface ICommsServiceFactory
{
ICommsService Create();
}

as3 assign another class to an existing class varriable?

I want to apply a new class to the same var name.
My code:
public var One:Word;
//later called
One = new Word();
// later changed
One = new redWord();
How do I change the var "One" from the class name "Word" to the new class name "redWord"?
You can use class wildcards if you want to be able to assign variables of multiple types to a var:
public var One:*;
Alternatively if both of your classes extend the same class you can use that as the base class for your var:
public class Words{
...
}
public class Poem extends Words{
...
}
public class Prose extends Words{
...
}
public var Soliloquy:Words;
By convention, variable names use lower case and class names use upper case. I would recommend changing One to one and redWord to RedWord.
To be able to assign to One instances of both Word and redWord, it must be declared of a type that is compatible with both. A possibility would be Object, but that may be too generic. Check if there is a common superclass to Word and redWord, and make One of that type.
The more specific your type is, the more errors you will discover at compile time, and the less nasty surprises you will be likely to find at runtime.

Robotlegs wiring up dependencies that belong to a base class

I'm using robot legs, I've got a bunch of ServiceResponses that extends a base class and have a dependency on a Parser, IParser. I need to wire in a parser specific to the subclass. Here's an example:
ModuleConfigResponse extends SimpleServiceResponse and implements IServiceResponse.
The initial part is easy to wire in the context, here's an example:
injector.mapClass(IServiceResponse, ModuleConfigResponse);
injector.mapClass(IServiceResponse, SimpleServiceResponse, "roomconfig");
..etc
Each Response uses a parser that is used by the baseclass:
injector.mapValue(IParser, ModuleConfigParser, "moduleconfig");
injector.mapValue(IParser, RoomConfigParser, "roomconfig");
The question is how to tie these together. The base class could have:
[Inject]
public var parser : IParser
But I can't define the type ahead of time. Im wondering if there a nice way of wiring this in the context. For the moment I've decided to wire this up by instanciating responses in a ResponseFactory instead so that I pay pass the parser manually in the constructor.
injector.mapValue(IParser, ModuleConfigParser, "moduleconfig");
I realised that not everything can be mapped in the context, RL trapped me into this way of thinking. But I've realised that its far better to map a factory to produce these objects which have very specific dependencies, than littler the codebase with marker interfaces or strings :)
one solution is to have the following in your base class:
protected var _parser : IParser
Then for instance in ModuleConfigResponse
[Inject(name='moduleconfig')]
public function set parser( value : IParser ) : void{
_parser = value;
}
But TBH, using named injections is STRONGLY discouraged, you might as well use a marker interface:
public interface IModuleConfigParser extends IParser{}
the base class stays the same, but ModuleConfigResponse would then use:
[Inject]
public function set parser( value : IModuleConfigParser ) : void{
_parser = value;
}

How do I register multiple services with a specific interface in Castle Windsor

I have the following registration:
container.Register(AllTypes.FromAssemblyContaining<ITabViewModel>().BasedOn<ITabViewModel>());
Two classes:
public class StructureDecorationViewModel : NotificationObject, ITabViewModel
{
...
}
public abstract class NotificationObject : INotifyPropertyChanged
{
...
}
And two resolvers:
serviceProvider.ResolveAll<System.ComponentModel.INotifyPropertyChanged>()
serviceProvider.ResolveAll<ITabViewModel>()
Both of these Resolvers gives the StructureDecorationViewModel, how can I filter the registration so that I only register the ITabViewModel and not the INotifyPropertyChange?
To register against just one interface you would normally use FirstInterface:
AllTypes
.FromAssemblyContaining<ITabViewModel>()
.BasedOn<ITabViewModel>()
.WithService
.FirstInterface();
However in this case you would end up with your service registered against INotifyPropertyChanged which is not what you want as it picks the first interface from the base class (Have a look at the ServiceDescriptor class to see what other registrations are available).
What you need is the Select method that allows you to define the type or types you want to register the service against:
AllTypes
.FromAssemblyContaining<ITabViewModel>()
.BasedOn<ITabViewModel>()
.WithService
.Select(typeof(ITabViewModel));
However if you want to keep things more generic someone has written an extension method that looks at the service being registered and picks out the first interface on the derived class (http://www.hightech.ir/SeeSharp/windsor-registration-service-interface):
public static BasedOnDescriptor FirstInterfaceOnClass(this ServiceDescriptor serviceDescriptor)
{
return serviceDescriptor.Select((t, bt) =>
{
var baseInterfaces = t.BaseType.GetInterfaces();
var interfaces = t.GetInterfaces().Except(baseInterfaces);
return interfaces.Count() != 0 ? new[] {interfaces.First()} : null;
});
}
Which allows you to do this:
AllTypes
.FromAssemblyContaining<ITabViewModel>()
.BasedOn<ITabViewModel>()
.WithService
.FirstInterfaceOnClass();

Refer to a Spark view component in code

I'm building a mobile AIR app using Flash Builder 4.5. The initial view in my views package is TestHomeView.mxml. I want to refer to it in one of my .as classes elsewhere in the app, and I'm not sure how to do that.
Theoretically I should be able to add an "id" attribute to TestHomeView.mxml, but FB gives me an error: "id is not allowed on the root tag of a component". The root tag is s:view.
The reason I need to do this is that within another class I make various calculations and then need to pass an array of values to a component in my view class. So in SomeOtherActionScriptClass.as I first assemble the array, myArray, and then in that class I want to do this:
myViewComponent.viewArray = myArray;
If I'm going to do that, I also need to import the view class into the .as class, which strikes me as weird. So is there a simple way to do what I want, or do I have to dispatch a custom event which contains the array, and listen for it in the view class?
EDIT - Based on the below MVC suggestion I did the following in model:
[Bindable]
public class Model
{
private static var myModel:Model;//doesn't let me name it 'model' because
//I have a package named 'model'
public var myArray:Array; //its value set later in model code
public function Model()
{
if ( Model.myModel != null ){
throw new Error( "Only one Model instance should be instantiated" );
}
}
// singleton: always returns the one existing static instance to itself
public static function getInstance() : Model {
if ( myModel == null ){
myModel = new Model();
}
return myModel;
}
Then in the view code I have:
[Bindable] //do I actually need this?
private var myModel:Model = Model.getInstance();
var viewArray = new Array();
viewArray = myModel.myArray;
But it is coming back null. It isn't null when I put a breakpoint in the Model class, but when I try to access it from the view class, it's null. The model itself isn't null, but that variable is.
What am I doing wrong?
Thanks.
First, if you are trying to make a singleton in AS3 you should first create a class, within the same class file as Model, that is used to ensure you can only create the class once.
Add this class at the bottom of the Model class file (outside of the Model class):
internal class SingletonEnforcer{}
Then create the Model constructor like this:
public function Model(enforcer:SingletonEnforcer){ Init(); } // if init code is needed
public static function get Instance():Model
{
if (!myModel){
myModel = new Model(new SingletonEnforcer());
}
return myModel;
}
Now you don't have to throw an exception for creating a second instance because it isn't possible.
I'm not sure about your first question of referencing your app's main mxml, but if you were asking how to call the app that is running (like WindowedApplication in AIR) then you would call it like this:
// my WindowedApplication file = MyApp.mxml
MyApp(this.parentApplication)
That will return the app's instance.
Once you've set up the Singleton like I have it above you should be able to access your array like:
Model.Instance.myArray;
I hope this helps!
Follow the MVC pattern.
Create Model class (make it Bindable) with a property viewArray. Bind to this property from your View. And in any other class just change viewArray property of the model. The binding event will be fired and this property will also be changed in your View. To make your Model "visible" from any point, you can make it a Singleton.