I am using NUnit3 and trying to make use of TestFixtureSource in the following class hierarchy:
public class AtataTestFixtureData
{
public static IEnumerable FixtureParams
{
get
{
yield return new TestFixtureData(new AtataConfigContainer
{
AtataJsonConfig = new BaseAtataConfig()
});
}
}
}
[TestFixtureSource(typeof(AtataConfigContainer), nameof(AtataTestFixtureData.FixtureParams))]
public class AtataTestsWithDbBase : OzCsTestsWithDbBase, IAtataAbpTests
{
public AtataTestsWithDbBase()
{
}
public AtataTestsWithDbBase(AtataConfigContainer aAtataConfigContainer)
{
AtataAbpTestsAdapter = AtataAbpTestsAdapter.Instance;
AtataConfigContainer = aAtataConfigContainer;
}
}
public class SomeSiteComAuTestsBase : AtataTestsWithDbBase
{
public SomeSiteComAuTestsBase(AtataConfigContainer aAtataConfigContainer) : base(aAtataConfigContainer)
{
}
}
[TestFixture]
public class IndexTests : SomeSiteComAuTestsBase
{
/// <summary>
/// Class constructor.
/// </summary>
public IndexTests(AtataConfigContainer aAtataConfigContainer) : base(aAtataConfigContainer)
{
}
[Test]
public void Get()
{
//Arrange
//Act
IndexPageObject indexPage = Go.To<IndexPageObject>();
//Assert
}
}
When I run IndexTests.Get() I get the exception OneTimeSetUp: No suitable constructor was found but according to public IndexTests(AtataConfigContainer aAtataConfigContainer) : base(aAtataConfigContainer) I have the needed constructor.
What am I missing here?
You are getting this error because your IndexTests class has a constructor that takes parameters, but your TestFixtureSource is on a base class. The TestFixtureSource needs to be on your IndexTests. The TestFixtureSource attribute is not inherited.
Related
I am struggling to register with Autofac a hierarchy of classes and interfaces.
I have an interface IMyService defined as below:
public interface IMyService
{
void DoMyService();
}
And I have two abstract classes with implement this interface and called MyServiceA, and MyServiceB:
public abstract class MyServiceA : IMyService
{
public abstract DoMyService();
}
public abstract class MyServiceB : IMyService
{
public abstract DoMyService();
}
Moreover I have a second-level hierarchy for each of the two aforementioned services: MyServiceA1, MyServiceA2, MyServiceB1 and MyServiceB2:
public class MyServiceA1 : MyServiceA
{
public MyServiceA1() : base() {}
public void DoMyService()
{
// Implementation goes here
}
}
public class MyServiceA2 : MyServiceA
{
public MyServiceA2() : base() {}
public void DoMyService()
{
// Implementation goes here
}
}
public class MyServiceB1 : MyServiceB
{
public MyServiceB1() : base() {}
public void DoMyService()
{
// Implementation goes here
}
}
public class MyServiceB2 : MyServiceB
{
public MyServiceB2() : base() {}
public void DoMyService()
{
// Implementation goes here
}
}
I have in input two enums FirstEnum and SecondEnum used to select which of the four concrete types to instantiate:
public enum FirstEnum
{
SvcA,
SvcB
}
public enum SecondEnum
{
Svc1,
Svc2
}
I want to register IMyService and by providing two enums, It will automatically instantiate the good concrete type.
For instance, if I want to resolve an IMyService and I provide FirstEnum.SvcB and SecondEnum.Svc2, it should instantiate the concrete type MyServiceB2 class. Moreover this hierarchy might be updated by adding some other concrete types etc, so I need a generic way of doing it
Does anyone have a clue to help me?
Thanks
If you want to create a specific service dynamically depending on a set of parameters, this is a good use case for an abstract factory:
public interface IMyServiceFactory
{
IMyService Create(FirstEnum e1, SecondEnum e2);
}
public class MyServiceFactory : IMyServiceFactory
{
private readonly ILifetimeScope scope;
public MyServiceFactory(ILifetimeScope scope)
{
if (scope == null)
throw new ArgumentNullException("scope");
this.scope = scope;
}
public IMyService Create(FirstEnum e1, SecondEnum e2)
{
if (e1 == FirstEnum.SvcA)
{
if (e2 == SecondEnum.Svc1)
{
return scope.Resolve<MyServiceA1>();
}
else //svc2
{
return scope.Resolve<MyServiceA2>();
}
}
else //B
{
if (e2 == SecondEnum.Svc1)
{
return scope.Resolve<MyServiceB1>();
}
else //svc2
{
return scope.Resolve<MyServiceB2>();
}
}
}
}
And now your consumer need to get the factory injected instead of the service:
public class MyServiceConsumer
{
private readonly IMyServiceFactory factory;
public MyServiceConsumer(IMyServiceFactory factory)
{
this.factory = factory;
}
public void Do()
{
//var service = this.factory.Create
}
}
Registration :
Autofac.ContainerBuilder builder = new Autofac.ContainerBuilder();
builder.RegisterType<MyServiceA1>().AsSelf().AsImplementedInterfaces();
builder.RegisterType<MyServiceA2>().AsSelf().AsImplementedInterfaces();
builder.RegisterType<MyServiceB1>().AsSelf().AsImplementedInterfaces();
builder.RegisterType<MyServiceB2>().AsSelf().AsImplementedInterfaces();
builder.RegisterType<MyServiceFactory>().As<IMyServiceFactory>();
builder.RegisterType<MyServiceConsumer>();
//and quick test resolve
var container = builder.Build();
var test = container.Resolve<MyServiceConsumer>();
Consider this code:
http://try.haxe.org/#5AD6e
class Test
{
public static function main()
{
var foo = new FluentFoo(null, { bar: 1 }).hello();
}
}
class Foo
{
public function new(options:{ bar:Int }) {}
public function hello()
{
trace("Hi there");
}
}
class Fluent
{
private var parent:Null<Fluent>;
public function new(parent:Null<Fluent>)
{
this.parent = parent;
}
public function end()
{
if(parent != null) {
return parent;
}
throw 'Top level already reached';
}
}
class FluentFoo extends Fluent
{
public var base:Foo;
public function new(parent:Null<Fluent>, options:{ bar:Int })
{
super(parent);
base = new Foo(options);
}
public function hello()
{
base.hello();
return this;
}
}
I want to generate classes such as FluentFoo automatically.
In pseudohaxe code:
import haxe.Constraints.Constructible;
class Test
{
public static function main()
{
var foo = new Fluent<Foo>(null, { bar: 1 }).hello();
}
}
class Foo
{
public function new(options:{ bar:Int }) {}
public function hello()
{
trace("Hi there");
}
}
#:generic
#:genericBuild(FluentMacro.build())
class Fluent<T:Constructible<Dynamic -> Void>>
{
private var parent:Null<Fluent>;
private var base:T;
public function new(parent:Null<Fluent>, options:Dynamic)
{
this.parent = parent;
this.base = new T(options);
}
public function end()
{
if(parent != null) {
return parent;
}
throw 'Top level already reached';
}
}
class FluentMacro
{
public static function build()
{
//Get "T" public methods
//Add them to class calling this genericBuild method (in this example to Fluent_Foo)
//Modify them so they return "this"
}
}
I know that I can't use #:build as all I'd get from Context.getLocalType would be TInst(Fluent,[TInst(Fluent.T,[])]).
However, I'm not completely understanding haxe manual on generic builds - they are under the same section "Type building macros" as normal #:build, yet the build method is expected to return ComplexType, and not an array of fields. Is it possible at all to add fields in #:genericBuild?
Thank you
That was a bit more complex than I anticipated, but I did it. For other people to use: https://github.com/Misiur/Fluent
I've been studying this accepted answer to a similar question in which what I believe is a concrete factory returns an implementation based on a string argument on the factory method matching a named binding on the concrete implementation.
I'm struggling to get a slightly more complex example to work properly when the factory is an abstract factory, and I wish to use Ninject convention-based binding. Consider the following test:
[Fact]
public void VehicleBuilderFactory_Creates_Correct_Builder_For_Specified_Client()
{
// arrange
StandardKernel kernel = new StandardKernel();
kernel.Bind(typeof (IVehicleBuilderFactory<,>))
.ToFactory(() => new UseFirstArgumentAsNameInstanceProvider())
.InSingletonScope();
kernel.Bind(scanner => scanner
.FromThisAssembly()
.SelectAllClasses()
.WhichAreNotGeneric()
.InheritedFrom(typeof(IVehicleBuilder<>))
.BindAllInterfaces());
var bicycleBuilderFactory =
kernel.Get<IVehicleBuilderFactory<IVehicleBuilder<BlueBicycle>, BlueBicycle>>();
string country = "Germany";
string localizedColor = "blau";
// act
var builder = bicycleBuilderFactory.Create<IVehicleBuilder<BlueBicycle>>(country);
Bicycle Bicycle = builder.Build(localizedColor);
// assert
Assert.IsType<BlueBicycleBuilder_Germany>(builder);
Assert.IsType<BlueBicycle>(Bicycle);
Assert.Equal(localizedColor, Bicycle.Color);
}
Here's where I try juggling with torches & knives 'cause I saw it on the internet once:
public class UseFirstArgumentAsNameInstanceProvider : StandardInstanceProvider
{
protected override string GetName(MethodInfo methodInfo, object[] arguments) {
return methodInfo.GetGenericArguments()[0].Name + "Builder_" + (string)arguments[0];
// ex: Germany -> 'BlueBicycle' + 'Builder_' + 'Germany' = 'BlueBicyleBuilder_Germany'
}
protected override ConstructorArgument[] GetConstructorArguments(MethodInfo methodInfo, object[] arguments) {
return base.GetConstructorArguments(methodInfo, arguments).Skip(1).ToArray();
}
}
I get stabbed and set ablaze when I try to assign bicycleBuilderFactory with this error:
System.InvalidCastException was unhandled by user code
Message=Unable to cast object of type 'Castle.Proxies.ObjectProxy' to type 'Ninject.Extensions.Conventions.Tests.IVehicleBuilderFactory`2[Ninject.Extensions.Conventions.Tests.IVehicleBuilder`1[Ninject.Extensions.Conventions.Tests.BlueBicycle],Ninject.Extensions.Conventions.Tests.BlueBicycle]'.
Source=System.Core
StackTrace:
at System.Linq.Enumerable.<CastIterator>d__b1`1.MoveNext()
at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source)
at Ninject.ResolutionExtensions.Get[T](IResolutionRoot root, IParameter[] parameters) in c:\Projects\Ninject\ninject\src\Ninject\Syntax\ResolutionExtensions.cs:line 37
at Ninject.Extensions.Conventions.Tests.NinjectFactoryConventionsTests.VehicleBuilderFactory_Creates_Correct_Builder_For_Specified_Client() in C:\Programming\Ninject.Extensions.Conventions.Tests\NinjectFactoryConventionsTests.cs:line 40
InnerException:
Is it possible to bind using the ToFactory() method and custom provider, using the factory method argument ("Germany") along with the generic type argument (IVehicleBiulder<BlueBicycle>, BlueBicycle) to resolve the type?
Here's the rest of the code for the test, as compact and readable as I could make it.
public interface IVehicleBuilderFactory<T, TVehicle>
where T : IVehicleBuilder<TVehicle> where TVehicle : IVehicle
{
T Create<T>(string country);
}
VehicleBuilder implementations
public interface IVehicleBuilder<T> where T : IVehicle { T Build(string localizedColor); }
abstract class BicycleBuilder<T> : IVehicleBuilder<T> where T : Bicycle
{
public abstract T Build(string localizedColor);
}
public abstract class RedBicycleBuilder : IVehicleBuilder<RedBicycle>
{
private readonly RedBicycle _Bicycle;
public RedBicycleBuilder(RedBicycle Bicycle) { _Bicycle = Bicycle; }
public RedBicycle Build(string localizedColor)
{
_Bicycle.Color = localizedColor;
return _Bicycle;
}
}
public abstract class GreenBicycleBuilder : IVehicleBuilder<GreenBicycle>
{
private readonly GreenBicycle _Bicycle;
public GreenBicycleBuilder(GreenBicycle Bicycle) { _Bicycle = Bicycle; }
public GreenBicycle Build(string localizedColor)
{
_Bicycle.Color = localizedColor;
return _Bicycle;
}
}
public abstract class BlueBicycleBuilder : IVehicleBuilder<BlueBicycle>
{
private readonly BlueBicycle _Bicycle;
public BlueBicycleBuilder(BlueBicycle Bicycle) { _Bicycle = Bicycle; }
public BlueBicycle Build(string localizedColor)
{
_Bicycle.Color = localizedColor;
return _Bicycle;
}
}
public class RedBicycleBuilder_USA : RedBicycleBuilder {
public RedBicycleBuilder_USA(RedBicycle Bicycle) : base(Bicycle) { }
}
public class RedBicycleBuilder_Germany : RedBicycleBuilder {
public RedBicycleBuilder_Germany(RedBicycle Bicycle) : base(Bicycle) { }
}
public class RedBicycleBuilder_France : RedBicycleBuilder {
public RedBicycleBuilder_France(RedBicycle Bicycle) : base(Bicycle) { }
}
public class RedBicycleBuilder_Default : RedBicycleBuilder {
public RedBicycleBuilder_Default(RedBicycle Bicycle) : base(Bicycle) { }
}
public class GreenBicycleBuilder_USA : GreenBicycleBuilder {
public GreenBicycleBuilder_USA(GreenBicycle Bicycle) : base(Bicycle) { }
}
public class GreenBicycleBuilder_Germany : GreenBicycleBuilder {
public GreenBicycleBuilder_Germany(GreenBicycle Bicycle) : base(Bicycle) { }
}
public class GreenBicycleBuilder_France : GreenBicycleBuilder {
public GreenBicycleBuilder_France(GreenBicycle Bicycle) : base(Bicycle) { }
}
public class GreenBicycleBuilder_Default : GreenBicycleBuilder {
public GreenBicycleBuilder_Default(GreenBicycle Bicycle) : base(Bicycle) { }
}
public class BlueBicycleBuilder_USA : BlueBicycleBuilder
{
public BlueBicycleBuilder_USA(BlueBicycle Bicycle) : base(Bicycle) { }
}
public class BlueBicycleBuilder_Germany : BlueBicycleBuilder {
public BlueBicycleBuilder_Germany(BlueBicycle Bicycle) : base(Bicycle) { }
}
public class BlueBicycleBuilder_France : BlueBicycleBuilder
{
public BlueBicycleBuilder_France(BlueBicycle Bicycle) : base(Bicycle) { }
}
public class BlueBicycleBuilder_Default : BlueBicycleBuilder
{
public BlueBicycleBuilder_Default(BlueBicycle Bicycle) : base(Bicycle) { }
}
Vehicle implementations:
public interface IVehicle { string Color { get; set; } }
public abstract class Vehicle : IVehicle { public string Color { get; set; } }
public abstract class Bicycle : Vehicle { }
public class RedBicycle : Bicycle { }
public class GreenBicycle : Bicycle { }
public class BlueBicycle : Bicycle { }
Based on comments from #LukeN, I've refactored the Bicycle class, so that its color is set through constructor injection with an IColorSetter. The IColorSetter implementation has a generic Color type, and each of the Color implementations are 'localized' by way of constructor injection with an IColorLocalizer<T>.
This way, no class seems to have knowledge of anything beyond what is logically its responsibility (I think).
However, I'll need to think about this more to see how the refactored classes shown below can be used to show how to use a Ninject custom instance provider could be used to pick the property IColorLocalizer<T> now, since it's the only class that will know about colors and languages; the color coming from its generic type, and the language coming from the name of the implementation itself.
Since asking the original post, I've moved away from using an IoC container to make choices like this, choosing instead to programmatically put in code a switch for picking an implementation, with a default implementation selected for any unhandled outlier cases. But I'm not sure if it's mainly to get beyond something that's stumped me, or because it's a poor choice to lean on an IoC container in this way.
I'll need to update this answer more as I think about it.
Vehicles
public abstract class Vehicle {
public abstract string Color { get; internal set; }
public abstract string Move();
}
public class Bicycle : Vehicle {
public Bicycle(IColorSetter colorSetter) { colorSetter.SetColor(this); }
public override string Color { get; internal set; }
public override string Move() { return "Pedaling!"; }
}
Color setters
public interface IColorSetter { void SetColor(Vehicle vehicle); }
public class ColorSetter<T> : IColorSetter where T : Color
{
private readonly T _color;
public ColorSetter(T color) { _color = color; }
public void SetColor(Vehicle vehicle) { vehicle.Color = _color.Name; }
}
Color localizers
public interface IColorLocalizer<in T> where T : Color {
void LocalizeColor(T color);
}
public class GermanBlueLocalizer : IColorLocalizer<Blue> {
public void LocalizeColor(Blue color) { color.Name = "blau"; }
}
public class EnglishBlueLocalizer : IColorLocalizer<Blue> {
public void LocalizeColor(Blue color) { color.Name = "blue"; }
}
Colors
public abstract class Color { public string Name { get; internal set; } }
public class Red : Color {
public Red(IColorLocalizer<Red> colorLocalizer) {
colorLocalizer.LocalizeColor(this); }
}
public class Green : Color {
public Green(IColorLocalizer<Green> colorLocalizer) {
colorLocalizer.LocalizeColor(this); }
}
public class Blue : Color {
public Blue(IColorLocalizer<Blue> colorLocalizer) {
colorLocalizer.LocalizeColor(this); }
}
I think I am losing my mind. :)
I've been struggling with this for two days now. The code looks right. But for some reason when I try to access the [ImportMany] field, it is null, or at least not returning any values.
It get the 3 parts in the catalog, but they don't get applied to the Lazy[] import I am defining.
Here's my code:
using System;
using System.Linq;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
namespace MefTest
{
// Extension interface and metadata
public interface IUIExtension
{
void DoSomething();
}
public interface IUIExtensionDetails
{
string Name { get; }
string Uri { get; }
}
[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple=false)]
public class UIExtensionAttribute : ExportAttribute
{
public UIExtensionAttribute() : base(typeof(IUIExtensionDetails)) { }
public string Name { get; set; }
public string Uri { get; set; }
}
// Extensions
[UIExtension(Name="Test 01", Uri="http://www.yourmomma.com/")]
public class Test1Extension : IUIExtension
{
public void DoSomething() { }
}
[UIExtension(Name = "Test 02", Uri = "http://www.yourdaddy.com/")]
public class Test2Extension : IUIExtension
{
public void DoSomething() { }
}
[UIExtension(Name = "Test 03", Uri = "http://www.youruncle.com/")]
public class Test3Extension : IUIExtension
{
public void DoSomething() { }
}
// Main program
public class Program
{
static void Main(string[] args)
{
Program p = new Program();
p.Run();
}
[ImportMany]
public Lazy<IUIExtension, IUIExtensionDetails>[] Senders { get; set; }
public void Run()
{
Compose();
}
public void Compose()
{
var catalog = new AssemblyCatalog(
System.Reflection.Assembly.GetExecutingAssembly());
var container = new CompositionContainer(catalog);
container.ComposeParts(this);
// This is always 3
Console.WriteLine(
(from g in container.Catalog.Parts select g).Count());
// This is always 0
Console.WriteLine(Senders.Length);
Console.ReadKey();
}
}
}
Your error is here:
public UIExtensionAttribute() : base(typeof(IUIExtensionDetails))
You should pass the contract type there, not the metadata type:
public UIExtensionAttribute() : base(typeof(IUIExtension))
(Also, in order to make sure that your custom export class has the right properties as expected by the import with metadata, I would make it implement the IUIExtensionDetails interface. But that is not mandatory.)
Your metadata attribute is defining the exports as typeof(IUIExtensionDetails) which is your metadata contract, not your actual extension. Change the custom attribute constructor to:
public UIExtensionAttribute() : base(typeof(IUIExtension)) { }
Currently I have a class that looks like this:
public class MyClass : IMyClass
{
public MyClass()
{
//...
}
public MyClass(IMyRepository repository)
{
//...
}
}
In my config file I have IMyClass registered, but not IMyRepository. My intention is for Windsor to use the constructor that doesn't take any parameters, but I am getting this message:
Can't create component 'MyClass' as it
has dependencies to be satisified.
MyClass is waiting for the following
dependencies:
Services:
- Namespace.IMyRepository which was not registered.
I found another post that says that the container will call the constructor with the most arguments that it can satisfy. So why is it trying to call the constructor with an argument that it doesn't know how to satisfy?
Maybe you're using an old version of Windsor... this works just fine for me:
[TestFixture]
public class WindsorTests {
public interface ISomeInterface {}
public class AService {
public int Id { get; private set; }
public AService() {
Id = 1;
}
public AService(ISomeInterface s) {
Id = 2;
}
}
[Test]
public void Parameters() {
var container = new WindsorContainer();
container.AddComponent<AService>();
var service = container.Resolve<AService>();
Assert.AreEqual(1, service.Id);
}
}