I am using Ninject to perform dependency injection in my project and I've encountered one problem. I need to specify an exception in binding in specific subtrees of my "object tree" (in meaning of inclusion not inheritance). Let's say we have few interfaces and classes (I've excluded constructors and other irrelevant stuff):
interface Wheel { ... }
class RoundWheel : Wheel { ... }
class SquareWheel : Wheel { ... }
class Mechanism { Wheel Wheel; ... }
class Bike { Wheel Wheel; ... }
class Items { Mechanism Mechanism; Bike Bike; ... }
I want to bind Wheel to SquareWheel when it's somehow included in Mechanism (Mechanism can be somewhere higher, eg. Item.Mechanism.ContainerForWheel.(any types further on).Wheel) and to RoundWheel otherwise. Now, let's look at my current solution:
IKernel kernel = new StandardKernel();
kernel.Bind<Wheel>().To<RoundWheel>();
kernel.Bind<Wheel>().To<SquareWheel>().When(x => x.ActiveBindings.Any(p => p.Service.Name == typeof(Mechanism).Name));
Items items = kernel.Get<Items>();
It works like a charm, but looks very inelegant and suboptimal. It's hard to understand clear purpose of this filtering. Do you know any other way to achieve this? Thanks in advance.
Edit 1
I forgot to mention that I don't want to put any annotations and other stuff into my classes. I want to keep everything in kernel setup/modules.
I don't think there's really an easier way to do things. You could also explictly traverse the IContext.ParentRequest and check if there's ever a specific Mechanism. That would be a bit more explicit then using the ActiveBindings property. But will neither be faster nor result in less code.
But what you could do is applying clean code and creating your own When-Extension, so you'll end up with:
kernel.Bind<Wheel>().To<SquareWheel>()
.When(IsDescendantOf<Mechanism1>);
private static bool IsDescendantOf<T>(IRequest request)
{
return request.ActiveBindings.Any(p => p.Service.Name == typeof(T).Name);
}
or, using an extension method:
kernel.Bind<IWheel>().To<Wheel2>()
.WhenIsDescendantOf(typeof(Mechanism1));
public static class NinjectWhenExtensions
{
public static IBindingInNamedWithOrOnSyntax<T> WhenIsDescendantOf<T>(this IBindingWhenSyntax<T> syntax, Type ancestor)
{
return syntax.When(request => request.ActiveBindings.Any(p => p.Service.Name == ancestor.Name));
}
}
btw., you should also be able to replace the check p.Service.Name == typeof(Mechanism).Name by p.Service == typeof(Mechanism). When the name is a match, the type shoould be, too. If you're working with interface you would have to adapt the logic, though.
Related
So, I have a little bit of an issue that I can't exactly wrap my head around.
So, I have a base class called Property, and I have a lot of classes that derive from that one, like IntProperty, ColorProperty and so on. Now, I also have a few of them that are of the enum type and currently they are all separate classes. I'd like to make it a generic class but here's the issue with this:
In a different part of the code I need to handle all of them. Keep in mind I can't use virtual functions for this (I'm doing something with the UnityEditor).
Currently, I have a function that takes a Property as a parameter and then I do this for all types that derive from Property:
if(property is IntProperty)
{
IntProperty intProperty = property as IntProperty;
intProperty.theValue = specific_int_function();
}
That specific_int_function is the same for all enum values privided I have the T from a generic.
Ideally I'd like to do something like this (pseud-ish code):
(using T)
{
if(property is EnumProperty<T>)
{
EnumProperty<T> enumProperty = property as EnumProperty<T>;
enumProperty.value = (T)my_enum_value_function(typeof(T));
}
}
Any idea about how I could make all this code nicer?
Hopefully I provided all the relevant information.
Edit:
It's not so much that I can't use virtual functions in those classes but I can't call any of the specific functions in that particular file. I have 2 compilation groups and only one can access those functions (EditorGUI functions for people who know what I'm talking about)
Regards,
Lorin
Keep in mind I can't use virtual functions for this (I'm doing something with the UnityEditor).
That's really what you should be doing. If you can't, then fine, but I'm leaving this note here for the benefit of other people will be reading this question and answer too.
In my experience, the least difficult way of achieving this is with a helper class, because it lets you avoid some of the reflection complexity that you would have to deal with if you used a generic helper method.
abstract class EnumPropertyHelper {
public abstract void DoSomething(Property property);
}
class EnumPropertyHelper<T> : EnumPropertyHelper {
public override void DoSomething(Property property) {
EnumProperty<T> enumProperty = property as EnumProperty<T>;
enumProperty.value = (T)my_enum_value_function(typeof(T));
}
}
Then,
if (property.GetType().IsGenericType
&& property.GetType().GetGenericTypeDefinition() == typeof(EnumProperty<>)) {
var helperType = typeof(EnumPropertyHelper<>).MakeGenericType(property.GetType().GetGenericTypeArguments());
var helper = (EnumPropertyHelper)Activator.CreateInstance(helper);
helper.DoSomething(property);
}
But you do need to jump through hoops similar to this one whatever you end up doing, because C# and .NET don't allow you to have generic code in non-generic methods.
You could use add a function pointer to the class, and each constructor could implement it's own function?
Add a property Func<void> functionPTR = null
In each class you'd have a function such as
void specific_int_function() {
//Do Something
}
In the class constructor
functionPTR = specific_int_function;
And then in the generic class
void GenericHandler() {
functionPTR();
}
I'm not sure about the syntax, but this should give you the performance you're going for.
Read up on function pointers to see how to define the return value and function parameters.
I am using Ninject to create a set of "plugins", e.g. I have:
Bind<IFoo>().To<Class1>();
Bind<IFoo>().To<Class2>();
Bind<IFoo>().To<Class3>();
... and later on I use kernel.GetAll<IFoo>() and iterate over the results. Each of Class1/Class2/Class3 implement IFoo of course, and have constructors that have a bunch of parameters also injected by Ninject, for example the constructor for Class1 is public Class1(IBar bar, IBaz baz), with both IBar and IBaz injected by Ninject. So far so good.
However, now I want to have two different "versions" of Class1, both bound to IFoo, differing only in a value passed at construction time. That is, for example, suppose the Class1 constructor was now public Class1(IBar bar, IBaz baz, bool myParameter), and I want to do the following:
Bind<IFoo>().To<Class1>(); //Somehow pass 'true' to myParameter here
Bind<IFoo>().To<Class1>(); //Somehow pass 'false' to myParameter here
Bind<IFoo>().To<Class2>();
Bind<IFoo>().To<Class3>();
... Then, when I call kernel.GetAll<IFoo>(), I want 4 versions of IFoo returned (Class1 "true" version, Class1 false version, Class2 and Class3). I've read through the Ninject documentation and can't find a way to do this.
Here are some ideas I tried, but none of them work well:
1) I could just separate classes (e.g. Class1True and Class1False), with one deriving from another, and bind to them. The problem is that this solution doesn't really scale when I have to do this for many classes - I end up polluting my class hierarchy with a lot of useless classes, and the problem becomes worse when the constructor parameter I want to pass is anything more complex than a bool. Realistic example:
Bind<IDrawingTool>().To<Brush>(); //Somehow pass '5' to brushThickness to create a fine brush
Bind<IDrawingTool>().To<Brush>(); //Somehow pass '25' to brushThickness to create a medium brush
Bind<IDrawingTool>().To<Brush>(); //Somehow pass '50' to brushThickness to create a coarse brush
Bind<IDrawingTool>().To<Pencil>();
Bind<IDrawingTool>().To<SprayCan>();
Of course, this is just one possible configuration of infinitely many possible ones. Creating a new class for each brush thickness seems wrong.
2) I looked into the possibility of using a .ToMethod binding, something like this:
Bind<IDrawingTool>().ToMethod(c => new Brush(5));
Bind<IDrawingTool>().ToMethod(c => new Brush(25));
Bind<IDrawingTool>().ToMethod(c => new Pencil());
But in this case I'm confused about the following:
a) What if the Brush() constructor actually requires other parameters as well, that must be injected via Ninject?
b) Are multiple ToMethod bindings actually allowed?
c) Would this work with InSingletonScope()?
So to summarize: What is a good way to bind to multiple "versions" of the same type?
It's perfectly fine to create two bindings for the same type, which differ only in parameters.
So what you've got to do is:
Bind<IFoo>().To<Class1>().WithConstructorArgument("boolParameterName", true);
Bind<IFoo>().To<Class1>().WithConstructorArgument("boolParameterName", false);
Use the WithConstructorArgument to pass the parameter. You can either have Ninject match the parameter by the name - in the above example the Class1 ctor would need to feature a bool parameter whose name is exactly boolParameterName. Or you can match the type, in which case you could only have one parameter of that type in the constructor. Example: WithConstructorArgument(typeof(bool), true).
All the parameters which you don't specify by WithConstructorArgument get ctor-inject "as usual".
Complete working example (using xunit and FluentAssertions nuget packages):
public interface IBar { }
public class Bar : IBar { }
public interface IFoo { }
class Foo1 : IFoo
{
public Foo1(IBar bar) { }
}
class Foo2 : IFoo
{
public Foo2(IBar bar, bool theParametersName) { }
}
[Fact]
public void FactMethodName()
{
var kernel = new StandardKernel();
kernel.Bind<IBar>().To<Bar>();
kernel.Bind<IFoo>().To<Foo1>();
kernel.Bind<IFoo>().To<Foo2>().WithConstructorArgument("theParametersName", true);
kernel.Bind<IFoo>().To<Foo2>().WithConstructorArgument("theParametersName", false);
List<IFoo> foos = kernel.GetAll<IFoo>().ToList();
foos.Should().HaveCount(3);
}
If you don't use any conditional bindings, resolving those "multiple versions" at runtime when the container detects a dependency will result in an exception, due to ambiguity. It surely could work in a "service-locator"-based access, but in true DI composing the object graph, you'll run into trouble using this approach.
In your depicted scenario, this ambiguity would arise should the following hypothetical situation existed:
public class MyDraw
{
public MyDraw(IDrawingTool drawingTool)
{
// Your code here
}
}
kernel.Bind<IDrawingTool>().ToMethod(c => new Brush(5));
kernel.Bind<IDrawingTool>().ToMethod(c => new Brush(25));
kernel.Bind<IDrawingTool>().ToMethod(c => new Pencil);
// Runtime exception due to ambiguity: How would the container know which drawing tool to use?
var md = container.Get<MyDraw>();
However, if you have this class to be injected:
public class MyDraw
{
public MyDraw(IEnumerable<IDrawingTool> allTools)
{
// Your code here
}
}
This would work due to multi-injection. The caontainer would simply invoke all bindings that match IDrawingTool. In this case, multiple bindings are allowed, even ToMethod(...) ones.
What you need to do is rely upon mechanisms such as Named Bindings or Contextual Bindings (using WhenXXX(...) syntax, to let the target of injection to determine which concrete implementation it requires. Ninject has extensive support for this and actually is one of the defining features for it's core DI Framework. You can read about it here.
The challenge I am facing with Ninject currently is that when I use Rebind<>() it removes all bindings, even those that are conditional. Let me give you a silly example below. Basically what I find undesired behaviour in my case is that when Rebind is called it will remove the conditional WhenInjectedInto<T> binding instead of just overwriting the non-conditional Bind<T>. In the sample below the contract Contract.Assert(cat is Wild); in the ctor will fail after the Rebind.
Is there a way to do what I want - being the ability to keep already injected conditional bindings and overwrite only the non-conditional one?
P.S: In reality I am trying to do some interesting things with DataContext scopes depending on where they are injected (in a request or in an async command)
void Main()
{
StandardKernel kernel = new StandardKernel();
kernel.Bind<ICat>().To<Wild>();
kernel.Bind<ICat>().To<Wild>()
.WhenInjectedInto<EvilCat>();
kernel.Rebind<ICat>().To<Domestic>();
Contract.Assert(kernel.Get<ICat>() is Domestic);
kernel.Get<EvilCat>();
}
interface ICat {}
class Domestic : ICat {}
class Wild : ICat { }
class EvilCat
{
public EvilCat(ICat cat) {
Contract.Assert(cat is Wild);
}
}
Try this:
kernel.GetBindings(typeof(ICat)).
Where(binding => !binding.IsConditional).
ToList().
ForEach(
binding =>
kernel.RemoveBinding(binding)
)
kernel.Bind<ICat>().To<Domestic>();
Of course you can do it without LINQ in a foreach:
var bindings = kernel.GetBindings(typeof(ICat)).ToList();
foreach(var binding in bindings)
{
if (!binding.IsConditional)
kernel.RemoveBinding(binding);
}
kernel.Bind<ICat>().To<Domestic>();
The System.Windows.Documents namespace includes a number of classes with an Inlines property of type InlineCollection. For example, the Paragraph, Bold and Hyperlink classes all have this property.
Each of these classes is decorated with ContentPropertyAttribute ...
[ContentPropertyAttribute("Inlines")]
public class Paragraph : Block
... which means that it is easy enough, using reflection, to detect that a given object exposes this property.
However, I need to be able to access this property in a strongly-typed manner across a selection of the types that implement it.
I am a little surprised that Microsoft didn't make all these classes implement an "IInlineContainer" interface, which would have made type checking and casting very easy.
However, in the absence of such an interface, is there any way to fake this polymorphic functionality, ideally without littering my code with lots of conditions and type checking?
Many thanks for your ideas,
Tim
Edit:
Thanks for your suggestions. A number of people have suggested the idea of a wrapper class, but this is not possible in my situation, as the target objects are not created by my code, but by the other classes in the .NET framework, for example the Xaml parser or the RichTextBox control (in which the containing FlowDocument is being edited).
Edit 2:
There have been several great suggestions here and I thank everyone who shared their ideas. The solution I have chosen to implement employs extension methods, which was suggested by #qstarin, although I have refined the concept to suit my needs, as follows:
public static InlineCollection GetInlines(
this FrameworkContentElement element)
{
if (element == null) throw new ArgumentNullException("element");
if (element is Paragraph)
{
return ((Paragraph) element).Inlines;
}
else if (element is Span) // also catches Bold, Italic, Unerline, Hyperlink
{
return ((Span)element).Inlines;
}
else
{
return null;
}
}
Although this approach requires conditional logic and type casting (which I said I wanted to avoid) the use of extension methods means that it only needs to be implemented in one place, leaving my various calling methods uncluttered.
Extension methods.
public static class InlineContainerExtensions {
public static InlineContainer GetInlines(this Paragraph inlineContainer) {
return inlineContainer.Inlines;
}
public static InlineContainer GetInlines(this Bold inlineContainer) {
return inlineContainer.Inlines;
}
}
If you didn't need to access it in a strongly-typed manner, but just without reflection, you could use dynamic:
dynamic doc = new Bold()
doc.InlineCollection. ...
doc = new Paragraph()
doc.InlineCollection. ...
Another option is to define a wrapper, that exposes a property with the same name, and has an overloaded constructor that takes Bold, Paragraph, etc.
You could implement a wrapper class that exposes an Inlines property and delegates via reflection to the contained object.
Decide if you want to validate that the wrapped object indeed has Inlines in your constructor or when trying to reference it
Employ the Adapter Pattern, write one class for each of those classes you wish to handle, effectively wrapping them in a layer implementing a common layer.
To make the classes discoverable, I would use reflection, tag each such class with an attribute for which class they handle, ie.:
[InlineContainerAdapter(typeof(SpecificClass1))]
public class WrapSpecificClass1 : IInlineContainer
and use reflection to find them.
This would give you several benefits:
You don't have to deal with dynamic, or similar solutions
While you have to use reflection to find the classes, the code you're actually executing once you've created the adapter is 100% yours, hand-coded
You can create adapters for classes that doesn't really implement what you need in the same manner as the rest, by just writing the adapter different
If this sounds like an interesting solution, leave a comment and I'll put up a working complete example.
One way of doing this (apart from using dynamic, which is the easiest solution IMO), you can create dynamically generated methods to return the inlines:
Func<object, InlineCollection> GetInlinesFunction(Type type)
{
string propertyName = ...;
// ^ check whether type has a ContentPropertyAttribute and
// retrieve its Name here, or null if there isn't one.
if (propertyName == null)
return null;
var p = Expression.Parameter(typeof(object), "it");
// The following creates a delegate that takes an object
// as input and returns an InlineCollection (as long as
// the object was at least of runtime-type "type".
return Expression.Lambda<Func<object, InlineCollection>>(
Expression.Property(
Expression.Convert(p, type),
propertyName),
p).Compile();
}
You'd have to cache these somewhere, though. A static Dictionary<Type, Func<object, InlineCollection>> comes to mind. Anyway, when you have, you can simply make an extension method:
public static InlineCollection GetInlines(this TextElement element)
{
Func<object, InlineCollection> f = GetCachedInlinesFunction(element.GetType());
if (f != null)
return f(element);
else
return null;
}
Now, with this in place, just use
InlineCollection coll = someElement.GetInlines();
Because you can check in your GetCachedInlinesFunction whether the property really exists or not, and handle that in a neat fashion, you won't have to litter your code with try catch blocks like you have to when you're using dynamic.
So, your dream-code would be:
foreach (var control in controls) {
var ic = control as IInlineContainer;
if (ic != null) {
DoSomething(ic.Inlines);
}
}
I don't see why you don't want to create a strongly typed wrapper class that uses reflection. With this class (no error handling):
public class InlinesResolver {
private object _target;
public InlinesResolver(object target) {
_target = target;
}
public bool HasInlines {
get {
return ResolveAttribute() != null;
}
}
public InlineCollection Inlines {
get {
var propertyName = ResolveAttribute().Name;
return (InlineCollection)
_target.GetType().GetProperty(propertyName).GetGetMethod().Invoke(_target, new object[] { });
}
}
private ContentPropertyAttribute ResolveAttribute() {
var attrs = _target.GetType().GetCustomAttributes(typeof(ContentPropertyAttribute), true);
if (attrs.Length == 0) return null;
return (ContentPropertyAttribute)attrs[0];
}
}
You could almost get to your dream-code:
foreach (var control in controls) {
var ir = new InlinesResolver(control);
if (ir.HasInlines) {
DoSomething(ir.Inlines);
}
}
You could always superclass them (e.g. InlineParagraph, InlineBold, etc) and have each of your superclasses implement an IInlineContainer interface like you suggested. Not the quickest or cleanest solution, but you at least have them all descending from the same interface.
Depending on your use-case, you could create a public Api that delegated its work to a private method that takes a dynamic. This keeps the strong typing for your public Api and eliminates code duplication, even though it falls back to using dynamic internally.
public void DoSomethingwithInlines(Paragraph p) {
do(p);
}
public void DoSomethingwithInlines(Bolb b) {
do(b);
}
private void do(dynamic d) {
// access Inlines here, using c# dynamic
}
I have a class EqualCondition which implements my own interface ICondition, which has only one method: SatisfiedBy(Something).
public class EqualCondition : ICondition {
private Something m_Something;
public HelloCondition(Something something) {
m_Something = something;
}
// Magic!!!
public bool SatisfiedBy(Something something) {
return something == m_Something;
}
}
So ICondition is very simple to implement. Now I'm trying to create a CombinationCondition which also implements it. The idea is that CombinationCondition which will contain a list of IConditions which will determine whether SatisfiedBy will be successful or not.
My first thought was to make CombinationCondition implement IList<Something> but I quickly realized that I was only duplicating List<Something>. So why not just subclass it?
That idea sounded fine until I started thinking again about how to implement SatisfiedBy if I just subclassed List<Something>. I need to do:
return innerList.All(x => x.SatisfiedBy(something))
But how do I access the inner list?
Personally, for the use case you're showing, I would just make this implement IEnumerable<Condition>. You could then just implement the GetEnumerator by calling the (internal, encapsulated) List<Condition>'s method.
Potentially, ICollection<Condition> may make more sense (so you can add conditions at runtime), but only if you need that capability. Implementing IList<T> seems like overkill in this situation, for the use cases I'd see with this.
From what you have posted, I would just have CombinationCondition contain (encapsulate) a List<Something>. No need for the outside world to know it is a list unless absolutely necessary.
Edit 1:
public class CombinationCondition : ICondition {
private List<ICondition> list;
public CombinationCondition(List<ICondition> list) {
this.list = list;
}
// if you need it
public void AddCondition( ICondition condition ){
list.Add( condition );
}
// Still Magic!!!
public bool SatisfiedBy(Something something) {
return list.Any( x => x.SatisfiedBy( something ) );
}
}
Edit 2:
You might also consider renaming CombinationCondition to CompoundCondition...makes more sense, at least to me :)
I'm not sure I 100% understand what you are trying to do, but would this solve your need?
public interface ICondition<T>
{
bool SatisfiedBy(T something);
}
That way, you can just implement it for any generic type you need
One possibility would be a property of type IList<ICondition> called maybe "Conditions".
You don't need to access the inner list - you could access your class "itself".
However, prefer sublassing from ICollection<T>.