Ninject factory not working with conventions for me - c#

I am trying to use the method of binding located here but having no luck
https://github.com/ninject/ninject.extensions.factory/wiki/Factory-interface
https://github.com/ninject/ninject.extensions.factory/wiki/Factory-interface%3A-Referencing-Named-Bindings
Keep in mind I am not trying to do it this way:https://gist.github.com/akimboyko/4593576
Rather I am trying to use the convention GetMercedes() to mean
I am basically trying to achieve this:https://gist.github.com/akimboyko/4593576 with conventions specified in the above examples.
using Ninject;
using Ninject.Extensions.Factory;
using Ninject.Modules;
using Ninject.Parameters;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace Test.NinjectFactory
{
public class Program
{
public static void Main()
{
using (var kernel = new StandardKernel(new CarModule()))
{
var factory = kernel.Get<ICarFactory>();
var mercedes =factory.GetMercedes();
int i = 1;
}
}
public interface ICar
{
void Drive();
}
public class Mercedes : ICar
{
readonly ICarFactory carFactory;
public Mercedes(ICarFactory carFactory)
{
this.carFactory = carFactory;
}
public void Drive()
{
var Mercedes = this.carFactory.GetMercedes();
}
}
public interface ICarFactory
{
ICar GetMercedes();
}
public class CarModule : NinjectModule
{
public override void Load()
{
//https://github.com/ninject/ninject.extensions.factory/wiki/Factory-interface%3A-Referencing-Named-Bindings
Kernel.Bind<ICarFactory>().ToFactory();
Bind<ICar>().To<Mercedes>().NamedLikeFactoryMethod<ICarFactory>(x => x.GetMercedes());//doesnt work for me
}
}
}
}

I'm posting this as an answer because it is most likely the cause.
The factory extensions use prefixed Get methods as a standard. You'll run into issues by calling any of your factory methods with prefixed Get and using NamedLikeFactoryMethod. For example, GetFord, GetMercedes, GetNissan. You'll notice that, in the example at the link you provided, the function is called CreateMercedes.
Change your function name to CreateMercedes or anything that doesn't start with Get and it should be fine.

I found the anwswer here:
https://gist.github.com/akimboyko/5338320
It seems you need a function to take care of the binding
public class BaseTypeBindingGenerator<InterfaceType> : IBindingGenerator
{
public IEnumerable<IBindingWhenInNamedWithOrOnSyntax<object>> CreateBindings(Type type, IBindingRoot bindingRoot)
{
if (type != null && !type.IsAbstract && type.IsClass && typeof(InterfaceType).IsAssignableFrom(type))
{
string.Format("Binds '{0}' to '{1}' as '{2}", type, type.Name, typeof(InterfaceType)).Dump();
yield return bindingRoot.Bind(typeof(InterfaceType))
.To(type)
.Named(type.Name) as IBindingWhenInNamedWithOrOnSyntax<object>;
}
}
}

Related

C# - Overriding the return type from interface with a derived type using generics

My goal is to have a dictionary which stores different Container objects that derive from a interface IContainer. The user can
add different Container objects (as long as they implement IContainer) to this dictionary. The containers can add elements related to the
container (eg configContainer will add configElements, diContainer will add diConfigElements).
The elements also implement from a interface.
I want to avoid the scenario of DiConfigElements being added to ConfigContainer. I have looked at related questions and they dont quite solve my problem.
I feel that generics will solve my problem, I have a example but I get Argument 2: cannot convert from 'ConfigContainer' to 'IContainer'
I am using Unity C#.
test.cs
using System.Collections;
using System.Collections.Generic;
public class test
{
public Dictionary<string, IContainer<IResolveableItem>> containers;
// Use this for initialization
void Start()
{
containers = new Dictionary<string, IContainer<IResolveableItem>>();
ConfigContainer configContainer = new ConfigContainer();
ConfigContainerElement configElement = new ConfigContainerElement();
configElement.Name = "configTest";
configElement.Path = "configTest/configTest";
configContainer.Add("test1", configElement);
containers.Add("config",configContainer);
}
}
IContainer.cs
using System.Collections;
public interface IContainer<T> where T : IResolveableItem
{
void Add(string key , T value);
}
ConfigContainer.cs
using System.Collections.Generic;
public class ConfigContainer : IContainer<ConfigContainerElement>
{
public Dictionary<string, IResolveableItem> container = new Dictionary<string, IResolveableItem>();
public void Add(string key, ConfigContainerElement value)
{
throw new System.NotImplementedException();
}
}
ConfigContainerElement.cs
using System.Collections;
public class ConfigContainerElement : IResolveableItem
{
protected string name;
protected string path;
public string Name
{
get
{
return name;
}
set
{
name = value;
}
}
public string Path
{
get
{
return path;
}
set
{
path = value;
}
}
}
IResolveableItem.cs
using System.Collections;
public interface IResolveableItem
{
string Name { get; set; }
string Path { get; set; }
}
It's a limitation of generics, will have to use runtime checking.

Get field values from class within class

This has been driving me mad for a while now. I have a class which contains other classes. I need to loop through the first class looking for typeof second class then retreive the value of the fields.
the below code obviously fails on the line
Console.WriteLine(field.GetValue(mFC.field.secondClassString));
as this isn't a valid field. Possibly I'm going about this the wrong way - any ideas?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication4
{
class Program
{
static void Main(string[] args)
{
MyFirstClass mFC = new MyFirstClass();
FieldInfo[] fI = mFC.GetType().GetFields();
foreach (FieldInfo field in fI)
{
if (field.FieldType.Name == "MySecondClass")
{
//get the fields
Console.WriteLine(field.GetValue(mFC.field.secondClassString));
}
}
}
}
class MyFirstClass
{
public MySecondClass firstMSC = new MySecondClass("First Instance");
public MySecondClass secondMSC = new MySecondClass("Second Instance");
public string firstClassString = "I'm from the first class";
public int firstClassInt = 5;
}
class MySecondClass
{
public MySecondClass(string input)
{
this.secondClassString = input;
}
public string secondClassString;
public int secondClassInt = 10;
}
}
field.GetValue accepts the instance from which it gets the field value.
In your case I would expect it should be field.GetValue(mFC).
Also field.FieldType.Name == "MySecondClass" is not the best way to check the type as type name change will cause code to break. I recommend replacing it with field.FieldType == typeof(MySecondClass).
((MySecondClass)field.GetValue(mFC)).secondClassString;
use this inside console.writeline

Representing multiple values within one class member

I've been working on some electrical network simulation software (ElecNetKit). In electrical networks, sometimes it's convenient to work with single-phase models, sometimes in three-phase models.
As such, I would like to be able to represent one of the electrical network elements as:
class Bus
{
public Complex Voltage {set; get;} //single phase property
}
but simultaneously in a fashion so that the user can call Bus.Voltage.Phases[x], and expect a Complex for any valid integer x.
The Bus.Voltage property should map to Bus.Voltage.Phases[1] when treated as a Complex.
I've got two questions here:
Is this in violation of any OOP principles? I've got a feeling that it might be.
Is there a convenient way to represent this in C#?
In terms of representation, I've tried:
a class Phased<T> : T, but this is incompatible with the typing system, and
a class Phased<T> with a generic converter to type T, but the converter still needs to be invoked.
I'm aware that I can simply use something like:
public Dictionary<int,Complex> VoltagePhases {private set; get;}
public Complex Voltage {
set {VoltagePhases[1] = value;}
get {return VoltagePhases[1];}
}
but there's a lot of repetition once you start to do this for multiple properties, across multiple classes.
I would propose something like this:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Diagnostics;
using System.Numerics;
namespace Test
{
class PhaseList
{
private Dictionary<int, Complex> mPhases = new Dictionary<int, Complex>();
public Complex this[int pIndex]
{
get
{
Complex lRet;
mPhases.TryGetValue(pIndex, out lRet);
return lRet;
}
set
{
mPhases.Remove(pIndex);
mPhases.Add(pIndex, value);
}
}
}
class PhasedType
{
private PhaseList mPhases = new PhaseList();
public PhaseList Phases { get { return mPhases; } }
public static implicit operator Complex(PhasedType pSelf)
{
return pSelf.Phases[1];
}
public static implicit operator PhasedType(Complex pValue)
{
PhasedType lRet = new PhasedType();
lRet.Phases[1] = pValue;
return lRet;
}
}
class Bus
{
public PhasedType Voltage { get; set; }
}
class Program
{
static void Main(string[] args)
{
Bus lBus = new Bus();
lBus.Voltage = new Complex(1.0, 1.0);
Complex c = lBus.Voltage;
lBus.Voltage.Phases[1] = c;
c = lBus.Voltage.Phases[1];
}
}
}
Can you do something like this? This will work similar to your solution at the bottom but because of the generic class you are not repeating the code for each property.
class Program
{
static void Main(string[] args)
{
Collection<Complex> complex = new Collection<Complex>();
//TODO: Populate the collection with data
Complex first = complex.First;
Complex another = complex.Items[2];
}
}
public class Complex
{
// implementation
}
public class Collection<T> where T : class
{
public List<T> Items { get; set; }
public T First
{
get
{
return (Items.Count > 0) ? Items[1] : null;
}
set
{
if(Items.Count > 0)
Items[1] = value;
}
}
}

Inject an integer with Ninject

I have folowing class
public class Foo
{
public Foo(int max=2000){...}
}
and I want to use Ninject to inject a constant value into Foo. I have try this
Bind<Foo>().ToSelft().WithConstructorArgument("max", 1000);
but I get following error when I try to use _ninject.Get<Foo>:
Error activating int
No matching bindings are available, and the type is not self-bindable.
Activation path:
3) Injection of dependency int into parameter max of constructor of type Foo
the below works for me:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Ninject;
using Ninject.Activation;
using Ninject.Syntax;
public class Foo
{
public int TestProperty { get; set; }
public Foo(int max = 2000)
{
TestProperty = max;
}
}
public class Program
{
public static void Main(string [] arg)
{
using (IKernel kernel = new StandardKernel())
{
kernel.Bind<Foo>().ToSelf().WithConstructorArgument("max", 1000);
var foo = kernel.Get<Foo>();
Console.WriteLine(foo.TestProperty); // 1000
}
}
}

XML Serialisation question

I'm trying to teach-myself how to serialize/deserialize to/from XML using the attribute-based serializer. I've put the below code together for testing purposes but it seems that I might have missed a point or two. Can anyone assist me and tell me what to do to have the whole damn thing work properly? The code below should compile and run just fine but will throw an exception - something is probably wrong with my attributes.
What did I miss?
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.IO;
namespace XMLSerialisation_test
{
class Program
{
static void Main(string[] args)
{
World my_world = new World(new Point(20, 30));
for (int i = 0; i < 10; i++)
{
string property = String.Format("Property no.{0}", i);
my_world.PushWorldObject(new MyObject(new Point(i, i), property));
}
DataContractSerializer world_serializer = new DataContractSerializer(typeof(World));
try
{
using (Stream s = File.Create("output.xml"))
world_serializer.WriteObject(s, my_world);
}
catch (Exception e)
{
Console.WriteLine("Exception occured : {0}", e.Message);
}
}
}
}
WorldObject.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
namespace XMLSerialisation_test
{
[DataContract]
public struct Point // couldn't find the pre-defined Point for some reason
{
public Point(double x, double y)
{ X = x; Y = y; }
[DataMember]
public double X;
[DataMember]
public double Y;
}
[DataContract]
public abstract class WorldObject
{
public WorldObject() : this(0.0, 0.0)
{}
public WorldObject(Point loc)
{ m_location = loc; }
public WorldObject(double x, double y)
{
m_location.X = x;
m_location.Y = y;
}
[DataMember]
public Point Location
{
get { return m_location; }
set { m_location = value; }
}
protected Point m_location;
}
[DataContract]
public class MyObject : WorldObject
{
public MyObject(string prop)
: base(0.0, 0.0)
{ m_property = prop; }
public MyObject(Point p, string prop)
: base(p)
{ m_property = prop; }
[DataMember]
public string Property
{
get{ return m_property; }
set{ m_property = value; }
}
private string m_property;
}
}
World.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.Xml.Serialization;
namespace XMLSerialisation_test
{
[DataContract]
class World
{
public World() : this(new Point(10, 10))
{ }
public World(Point size)
{ m_world_size = size; }
public bool PushWorldObject(WorldObject o)
{
try
{
WorldObjects.Add(o);
return true;
}
catch(Exception e)
{
Console.WriteLine("Exception occured : {0}", e.Message);
return false; }
}
#region Accessors
[DataMember]
public List<WorldObject> WorldObjects
{
get { return m_world_objects; }
set { m_world_objects = value; }
}
[DataMember]
public Point WorldSize
{
get { return m_world_size; }
private set { m_world_size = value; }
}
#endregion
#region Fields
private List<WorldObject> m_world_objects = new List<WorldObject>();
private Point m_world_size;
#endregion
}
}
Try this:
DataContractSerializer world_serializer = new DataContractSerializer(typeof(World), new List<Type> { typeof(MyObject) });
The problem is that PushWorldObject takes type WorldObject, but you are actually passing type MyObject. The serializer knows nothing about this type, so throws an exception. WorldObject is used within the World class, so this type is by known by default. However, MyObject is not used inside World - so you manually have to declare it as Known.
As an alternative, you can add the KnownType attribute like so:
[DataContract, KnownType(typeof(MyObject))]
class World
{
The biggest problem I see is the abstract WorldObject. You'll need to use a KnownType attribute there (or via config or method name- check MSDN for "Data Contract Known Types") to tell it about the known subtypes it might encounter (eg, MyObject).
Just to clarify: if you are serializing to xml for the purposes of having xml in a known format, then DataContractSerializer is a bad choice; you would do better to use XmlSerializer, which has more control over xml layout. You would use the [XmlElement] / [XmlAttribute] / [XmlType] / [XmlRoot] attributes instead of [DataMember] etc.
If you just want to use xml because it is text and stores the object, then DataContractSerializer is fine; and has other advantages, for example - not demanding a public parameterless constructor (which XmlSerializer does), and working with private members (which XmlSerializer doesn't).

Categories

Resources