public interface IFoo : ICanCatch, ICanLog
{ void Bar () }
public class Foo : IFoo
{
public void Bar ()
{
Console.WriteLine ("Bar");
}
}
IWindsorContainer _Container;
[TestFixtureSetUp]
public void init ()
{
_Container = new WindsorContainer();
_Container.Register(
Component.For<LogInterceptor> (),
Component.For<ExceptionInterceptor> (),
Component
.For<ICanCatch>().ImplementedBy<Foo>().Interceptors<LogInterceptor>().Named ("loggableFoo"),
Component.For<ICanLog>().ImplementedBy<Foo>().Interceptors<ExceptionInterceptor>().Named ("catchableFoo"),
Component.For<IFoo>().ImplementedBy<Foo>()
);
}
[Test]
public void foo ()
{
var a = _Container.Resolve<IFoo> ();
a.Bar (); <-- Interceptors not working. IFoo is a ICanLog, ICanCatch
}
I'm trying to resolve Foo component by service IFoo but by this resolving it also implements the aspects (ICanLog, ICanCatch) given in container. Is there a solution to make real this one. (Mixin?)
You didn't attach any interceptors to IFoo.
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();
}
I have a vector in my Main class file that store objects. I will like to be able to add more objects to that SAME vector from a different class. I gave the vector in my main class the "public" modifier. I now need the syntax to reference it in my other class file
public var badChar:Vector.;
You have options. How you approach it is dependent on your project setup, and the needs of the property. Is it an instantiated object, or should there ever only be one (even if the class is instantiated multiple times)? Do you need direct access to it regardless of any relationship to the stage? Each solution below has pros and cons.
Class-to-Class via Stage
Assuming the following main foo.as class:
package {
public class Foo {
public var bool:Boolean = true;
}
}
Bar class:
package {
public class Bar extends Sprite {
import flash.events.Event;
public function Bar() {
addEventListener(Event.ADDED_TO_STAGE, accessFoo);
}
private function accessFoo(e:Event):void {
trace(this.parent["f"].bool); // traces "true"
}
}
}
Document Code:
var f:Foo = new Foo();
var b:Bar = new Bar();
addChild(b);
Inheritance
Foo Class:
package {
public class Foo {
public var bool:Boolean = true;
}
}
Bar Class
package {
public class Bar extends Foo {
public function Bar() {
trace(bool); // traces "true"
}
}
}
Class-to-Class via Static
Some disclaimers should be in order for Static properties, but I'll leave you to read up on those.
Foo Class:
package {
public class Foo {
public static var bool:Boolean = true;
}
}
Bar Class
package {
public class Bar {
public function Bar() {
trace(Foo.bool); // traces "true"
}
}
}
Direct Access via New Declaration
Foo Class:
package {
public class Foo {
public var bool:Boolean = true;
}
}
Bar Class
package {
public class Bar {
import Foo;
public function Bar() {
trace(new Foo().bool); // traces "true"
}
}
}
Access via Sharing
Foo Class:
package {
public class Foo {
public var bool:Boolean = true;
}
}
Bar Class
package {
public class Bar {
import Foo;
public var fluffy:Foo;
public function Bar() {
trace(fluffy.bool);
}
}
}
Document Code:
var f:Foo = new Foo();
var b:Bar = new Bar();
b.fluffy = f;
Note that after the third line in the document code, fluffy is no longer an undeclared variable and will now point to the f object, where the properties updated in it (such as bool) will reflect inside of Bar.
With Castle Windsor 3.2
I need to resolve service implementation on the fly depending on contextual parameters.
Here is basic example of what I want to do:
I have a service IFoo
public interface IFoo
{
object GetSomething();
}
Implemented by 2 different classes Foo1 and Foo2
public class FooBase
{
public int Number {get; private set;}
public FooBase(int number)
{
Number = number;
}
}
public class Foo1 : IFoo
{
public Foo1(int number):base(number)
public object GetSomething()
{
return "Foo1";
}
}
public class Foo2 : IFoo
{
public Foo2(int number):base(number)
public object GetSomething()
{
return "Foo2";
}
}
I want to call the castle windsor resolve method with number as parameter, and depending on the number I want to have Foo1 or Foo2 object:
var foo1 = container.Resolve<IFoo>(new {number= 1});
// foo1 is Foo1
var foo2 = container.Resolve<IFoo>(new {number= 2});
// foo2 is Foo2
I tried several potential solutions, but I'm realy confused because of the lack of Castle Windsor documentation and examples, adding to that most of the examples are not up to date and are using obsolete API.
So I have seen some example using the following concepts, but none of them seemed to much my requirement :
HandlerSelector
Typed Factory facility
UsingFactoryMethod
Here is the code that worked for me:
container = new WindsorContainer();
container.AddFacility<TypedFactoryFacility>();
container.Register(
Component.For<IFoo>().ImplementedBy<Foo1>().Named("Foo1"),
Component.For<IFoo>().ImplementedBy<Foo2>().Named("Foo2"),
Component.For<IFooFactory>().AsFactory(c => c.SelectedWith<FooSelector>())
);
Create a Foo factory :
public interface IFooFactory
{
IFoo CreateFoo(int number);
}
and a selector:
public class FooSelector : DefaultTypedFactoryComponentSelector
{
protected override string GetComponentName(System.Reflection.MethodInfo method, object[] arguments)
{
var argument = (int) arguments[0];
return string.Format("Foo{0}", argument);
}
}
use the following registration code:
container = new WindsorContainer();
container.AddFacility<TypedFactoryFacility>();
container.Register(
Component.For<FooSelector>,
Component.For<Foo1>(),
Component.For<Foo2>(),
Component.For<IFooFactory>().AsFactory(c => c.SelectedWith<FooSelector>())
);
Create a Foo factory :
public interface IFooFactory
{
IFoo CreateFoo(int number);
}
and a selector:
public class FooSelector : DefaultTypedFactoryComponentSelector
{
protected override Type GetComponentType(System.Reflection.MethodInfo method, object[] arguments)
{
var argument = (int) arguments[0];
if (argument == 1) return typeof (Foo1);
if (argument == 2) return typeof(Foo2);
throw new ApplicationException();
}
}
Now resolve the IFooFactory and call the create methode with the value that you want.
Kind regards,
Marwijn.
When attempting to register a startable component that depends on a service whose implementation "decorates" the same service interface, Castle fails to resolve the startable component, claiming that the dependency cannot be resolved. Curiously enough, explicitly resolving the startable component works as expected. I have seen this behavior in both Castle Windsor 2.5 and 2.5.1. Please see the below NUnit test case:
UPDATE
I've discovered that I can get the startable mechanism to work, but I need to separate the registrations of the IFoo implementers into a separate container.Register() call from the registration of the startable component. The IFoo registrations must happen first. Even more interestingly, this does not work if I use an IWindsorInstaller to install the components. Please see additional test cases below:
UPDATE
Installing the IFoo implementers in a separate installer, in a separate call to container.Install() works. Installing the startable component by including its IWindsorInstaller in the params[] list to a single call to container.Install() does not work, but installing it in a separate call to container.Install() does work. I have consolidated all test cases into the below code snippet:
using System;
using Castle.Facilities.Startable;
using Castle.MicroKernel.Registration;
using Castle.MicroKernel.SubSystems.Configuration;
using Castle.Windsor;
using NUnit.Framework;
namespace Tests
{
[TestFixture]
public class TestProblemsWithStartableAndDecorators
{
/// <summary>
/// This test passes with the following output to the console:
///
/// foo decorator
/// typeof decorated : Foo
/// startable constructor
/// typeof foo : FooDecorator
///
/// </summary>
[Test]
public void TestUsingResolve()
{
using (var container = new WindsorContainer())
{
container.AddFacility<StartableFacility>(f => f.DeferredStart());
container.Register(
Component.For<IFoo>().ImplementedBy<FooDecorator>(),
Component.For<IFoo>().ImplementedBy<Foo>(),
Component.For<IGetStarted>().ImplementedBy<GetStarted>()
);
container.Resolve<IGetStarted>();
}
}
/// <summary>
/// This test should pass with the same output as the above test.
/// However, it fails with the following exeption:
///
/// Castle.MicroKernel.Handlers.HandlerException : Can't create component 'Tests.TestProblemsWithStartableAndDecorators+FooDecorator' as it has dependencies to be satisfied.
/// Tests.TestProblemsWithStartableAndDecorators+FooDecorator is waiting for the following dependencies:
///
/// Services:
/// - Tests.TestProblemsWithStartableAndDecorators+IFoo.
/// A dependency cannot be satisfied by itself, did you forget to add a parameter name to differentiate between the two dependencies?
///
/// Tests.TestProblemsWithStartableAndDecorators+foo is registered and is matching the required service, but cannot be resolved.
/// </summary>
[Test]
public void TestUsingStartable()
{
using (var container = new WindsorContainer())
{
container.AddFacility<StartableFacility>(f => f.DeferredStart());
container.Register(
Component.For<IFoo>().ImplementedBy<FooDecorator>(),
Component.For<IFoo>().ImplementedBy<Foo>(),
Component.For<IGetStarted>().ImplementedBy<GetStarted>().Start()
);
}
}
public interface IFoo
{
}
public class Foo : IFoo
{
}
public class FooDecorator : IFoo
{
public FooDecorator(IFoo decorated)
{
Console.WriteLine("foo decorator");
Console.WriteLine(" typeof decorated : " + decorated.GetType().Name);
}
}
public interface IGetStarted
{
}
public class GetStarted : IGetStarted
{
public GetStarted(IFoo foo)
{
Console.WriteLine("startable constructor");
Console.WriteLine(" typeof foo : " + foo.GetType().Name);
}
}
// works
[Test]
public void TestUsingStartableWithSeparateRegistrations()
{
using (var container = new WindsorContainer())
{
container.AddFacility<StartableFacility>(f => f.DeferredStart());
container.Register(Component.For<IFoo>().ImplementedBy<FooDecorator>(),
Component.For<IFoo>().ImplementedBy<Foo>());
container.Register(Component.For<IGetStarted>().ImplementedBy<GetStarted>().Start());
}
}
// fails
[Test]
public void TestUsingStartableWithSeparateRegistrationsRegisteringStartableFirst()
{
using (var container = new WindsorContainer())
{
container.AddFacility<StartableFacility>(f => f.DeferredStart());
container.Register(Component.For<IGetStarted>().ImplementedBy<GetStarted>().Start());
container.Register(Component.For<IFoo>().ImplementedBy<FooDecorator>(),
Component.For<IFoo>().ImplementedBy<Foo>());
}
}
// fails
[Test]
public void TestUsingStartableWithInstaller()
{
using (var container = new WindsorContainer())
{
container.AddFacility<StartableFacility>(f => f.DeferredStart());
container.Install(new TestInstaller());
}
}
public class TestInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container,
IConfigurationStore store)
{
container.Register(Component.For<IFoo>().ImplementedBy<FooDecorator>(),
Component.For<IFoo>().ImplementedBy<Foo>());
container.Register(Component.For<IGetStarted>().ImplementedBy<GetStarted>().Start());
}
}
// works
[Test]
public void TestUsingStartableWithSeparateFooInstaller()
{
using (var container = new WindsorContainer())
{
container.AddFacility<StartableFacility>(f => f.DeferredStart());
container.Install(new FooInstaller());
container.Register(Component.For<IGetStarted>().ImplementedBy<GetStarted>().Start());
}
}
// fails
[Test]
public void TestUsingStartableWithSeparateInstallers()
{
using (var container = new WindsorContainer())
{
container.AddFacility<StartableFacility>(f => f.DeferredStart());
container.Install(new FooInstaller(), new StartableInstaller());
}
}
// works
[Test]
public void TestUsingStartableWithSeparateCallsToInstall()
{
using (var container = new WindsorContainer())
{
container.AddFacility<StartableFacility>(f => f.DeferredStart());
container.Install(new FooInstaller());
container.Install(new StartableInstaller());
}
}
public class FooInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container,
IConfigurationStore store)
{
container.Register(Component.For<IFoo>().ImplementedBy<FooDecorator>(),
Component.For<IFoo>().ImplementedBy<Foo>());
}
}
public class StartableInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container,
IConfigurationStore store)
{
container.Register(Component.For<IGetStarted>().ImplementedBy<GetStarted>().Start());
}
}
}
}
Fixed in HEAD. Will be part of 2.5.2 release. For future reference, here's the bug report.
Considering this code :
interface IRepository<T>
{
void Save();
}
class Repository<T>
{
public virtual void Save() // something
{ }
}
interface IOtherRepository : IRepository<OtherClass>
{
void Other();
}
class OtherRepository : Repository<OtherClass>, IOtherRepository
{
public override void Save() // something different
{ }
public override void Other(){ }
}
How is it possible to configure Castle Windsor to give me an instance of OtherRepository when I call container.Resolve<IRepository<OtherClass>> ?
If Castle Windsor can't do this, which ioc containers can ?
var container = new WindsorContainer();
container.Register(Component.For(typeof(IRepository<>))
.ImplementedBy(typeof(Repository<>));
container.Register(Component.For<IRepository<OtherClass>, IOtherRepository>()
.ImplementedBy<OtherRepository>());
var repo = container.Resolve<IRepository<Something>>();
Assert.IsInstanceOfType(typeof(Repository<Something>), repo);
var specificRepo = container.Resolve<IRepository<OtherClass>>();
Assert.IsInstanceOfType(typeof(OtherRepository), specificRepo);
var otherRepo = container.Resolve<IOtherRepository>();
Assert.AreSame(otherRepo, specificRepo);