Specifying One of Many Constructor Parameters With StructureMap - structuremap

If I have a class like so:
public SomeClass : ISomeClass
{
public SomeClass(IInjectedDependency dependency, bool someArbitraryValue) {}
}
How can I set this up with SM to inject the dependency but specify the arbitrary value?
I've tried the following but it doesn't work (I get "There is no argument of type System.Boolean for concrete type IInjectedDependency"):
ObjectFactory.Initialize(x =>
{
x.For<IInjectedDependency>().Use<ConcreteDependency>();
x.For<ISomeClass>().Use<SomeClass>().Ctor<bool>("someArbitraryValue").Is(false);
});
I think this is only for a constructor with one parameter and thats why it doesn't work with multiple (I've used it for one param constructors and it works fine).
TIA!
m

Works like it should. Problem on my end.

Related

Check if a type implements an interface [duplicate]

I've recently found myself in a situation where I wanted to check if a Type is a subtype of another Type this is what I've tried
abstract class Record{}
class TimeRecord extends Record{}
void test(){
print(TimeRecord is Record); // return false but why ??
}
The only time it makes sense to check if one type is a subtype of another type is when at least one of the types is a type variable. (Otherwise, you can just look at the source and write a constant true or false into the code).
There is a way to check whether one type is a subtype of another, and it does use the is operator, but you need to have an instance as the first operand and a type as the second. You can't just create an instance of an unknown type, so we instead rely in Dart's covariant generics:
bool isSubtype<S, T>() => <S>[] is List<T>;
(You can use any generic class, or even create your own, instead of using List. All it needs is a way to create the object.)
Then you can write:
print(isSubtype<TimeRecord, Record>()); // true!
The is keyword is used to check if an object instance is an object of type T, and not if a type is another type:
abstract class Record{}
class TimeRecord extends Record{}
void test(){
print(TimeRecord() is Record); // returns true!
}
Just to add up to #lrn answer.
You could also do something like:
extension NullableObjectsExtensions<T> on T {
bool isSubtypeOf<S>() => <T>[] is List<S>;
bool isSupertypeOf<S>() => <S>[] is List<T>;
}
So this way you can test any variable anywhere.

e4 dependency reinjection order: field vs. method

I was quite surprised to see that there is no deterministic behavior for the order in which objects get reinjected.
public class Test {
#Inject private Boolean testBool;
#Inject
public void checkNewObject(Boolean testBoolNew) {
if (!testBoolNew.equals(this.testBool)) {
System.out.println("Out of sync!");
} else {
System.out.println("In sync!");
}
}
}
And this is how I use the class:
context.set(Boolean.class, new Boolean(true));
Test test = ContextInjectionFactory.make(Test.class, context);
context.set(Boolean.class, new Boolean(false));
So, sometimes I get the output:
In sync!
In sync!
And sometimes I get:
In sync!
Out of sync!
Is this really non deterministic or am I just overseeing something?
The documentation clearly states that the injection order should be:
Constructor injection: the public or protected constructor annotated with #Inject with the greatest number of resolvable arguments is selected
Field injection: values are injected into fields annotated with #Inject and that have a satisfying type
Method injection: values are injected into methods annotated with #Inject and that have satisfying arguments
See: https://wiki.eclipse.org/Eclipse4/RCP/Dependency_Injection#Injection_Order
I'm not sure, why this doesn't work as expected in your case.
How is equals() implemented in MyContent?
Is MyContent annotated with #Creatable and or #Singleton?
As a side note: Is this a practical or just an academic problem? Why is it necessary to inject the same instance into a field and into a method on the same target-instance? If you want to have a field variable to cache the value, you can set this from the method.
If you feel this is a bug, please file it here: https://bugs.eclipse.org/bugs/enter_bug.cgi?product=Platform

castle windsor - batch registration works on some classes only

I am have the following row to batch register implementations:
container.Register(Types.FromAssembly(typeof (BaseBll<>).Assembly)
.BasedOn(typeof (ICrudBll<>)).WithServiceAllInterfaces());
it works on 2 classes out of 4 event though they are exactlly the same.
public interface ICrudBll<T>{} //main interface
public interface IBrandBll : ICrudBll<Brand>{}
public class BrandBll : BaseBll<Brand>, IBrandBll{}// WORKING
public interface IRoleBll : ICrudBll<Role>{}
public class RoleBll : BaseBll<Role>, IRoleBll{}// NOT WORKING
it is suppose to be injected to:
//WORKING
public class BrandController : BaseApiController<Brand>
{
public BrandController(IBrandBll bll) : base(bll)
{
}
}
// NOT WORKING
public class RoleController : BaseApiController<Role>
{
public RoleController(IRoleBll bll)
: base(bll)
{
}
}
I dont see any differences between the classes and the interfaces, but yet some works and some not. (they are all in the same assembly).
This is the ERROR:
Type CrudApp.BusinessLogic.IUserBll is abstract.
As such, it is not possible to instansiate it as implementation of service 'CrudApp.BusinessLogic.IUserBll'. Did you forget to proxy it?
Again, the IBrandBll is working and the IRoleBll not.
I made a test, and injected the failed ones explicitly, and it worked:
container.Register(Component.For<IRoleBll>().ImplementedBy<RoleBll>().LifestyleTransient());
Thanks
Try changing:
container.Register(Types.FromAssembly(typeof (BaseBll<>).Assembly)
.BasedOn(typeof (ICrudBll<>)).WithServiceAllInterfaces());
to
container.Register(Classes.FromAssembly(typeof (BaseBll<>).Assembly)
.BasedOn(typeof (ICrudBll<>)).WithServiceAllInterfaces());
The statements above will also register interfaces, and it seems you only want classes to be registered.
this is actually what worked:
var types = AllTypes
.FromAssembly(typeof (ICrudBll<>).Assembly)
.BasedOn(typeof (ICrudBll<>))
.WithService.FromInterface(typeof (ICrudBll<>));
container.Register(types);
The error clearly states the problem is with IUserBll - not shown in your code snippets.
I bet IUserBll inherits from ICrudBll, which would explain the error - try to narrow down the type selection criteria to classes, excluding the interfaces:
Types.FromAssembly(typeof (BaseBll<>).Assembly)
.BasedOn(typeof (ICrudBll<>))
returns everything, including interfaces. Try something like
Types.FromAssembly(typeof (BaseBll<>).Assembly)
.Where(t => t.IsClass)
.BasedOn(typeof (ICrudBll<>))

Resolving a constructor with two arguments of the same interface?

Another developer and had this conversation today:
Me: Dependency Injection is cool, lol.
Dennis: What happens when I need an instance of the DoStuff class and the only constructor I have is DoStuff( ISomeInterface interface1, ISomeInterface interface2 ) where the concrete types are completely different?
Me: ...
We use Unity as our preferred container. How would I register that when I need to resolve ISomeInterface that the concrete type can be two different types?
Take a look at the ParameterOverride class. It allows you to specify parameters by name:
container.Resolve<IDoStuff>(new ParameterOverrides<DoStuff> { { "interface1", new SomeInterfaceImpl() }, { "interface2", AnotherSomeInterfaceImpl() } });

Castle Windsor can't inject an array of interface types

I have a class that takes an array of interfaces in the constructor:
public class Foo<T1, T2> : IFoo<T1, T2>
{
public Foo(IBar[] bars)
{
...
}
}
My container registration looks as follows:
container.Register(AllTypes.Pick().FromAssemblyNamed("...")
.WithService.FirstInterface());
container.AddComponent("foo", typeof(IFoo<,>), typeof(Foo<,>));
I have several implementations of IBar, and the container can definately locate them, as calling ServiceLocator.Current.GetAllInstances<IBar>() works fine.
However, if I try to get an instance of IFoo, it throws an exception saying it couldn't satisfy the deoendency... "which was not registered".
If I change the constructor to take a single instance of IBar it works fine.
Any ideas?
Add the ArrayResolver:
container.Kernel.Resolver.AddSubResolver(new ArrayResolver(container.Kernel));

Resources