Inject an integer with Ninject - c#

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
}
}
}

Related

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

Ninject factory not working with conventions for me

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>;
}
}
}

Linq-ing Calculated Properties in nhibernate could not resolve property Error

I have been trying to create a calculated property in my persistence layer by follow
Hendry Luk's solution for calculated properties.
I am able to select the values from the DB using a linq query:
var result = from parcel in Repository.Query();
When I try to do a where on the selected result, I get a could not resolve property error.
Here is what my code looks like.
My Model:
namespace ConsoleApplication14
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
public class Common1 : ICommon
{
public virtual int Id { get; set; }
public virtual string Name { get; set; }
//public static readonly Expression<Func<Common1, string>> CalculatedDisplayExpression = x => ("Common 1 Display: " + x.Id + " - " + x.Name);
public static readonly Expression<Func<Common1, string>> CalculatedDisplayExpression = x => (x.Id + "");
private static readonly Func<Common1, string> CalculateDisplay = CalculatedDisplayExpression.Compile();
public virtual string Display { get { return CalculateDisplay(this); } }
}
}
My Interface the model implementing:
namespace ConsoleApplication14
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;`enter code here`
public interface ICommon
{
int Id { get; set; }
string Name { get; set; }
string Display { get; }
}
}
Model's mapping
namespace ConsoleApplication14
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate.Mapping.ByCode;
using NHibernate.Mapping.ByCode.Conformist;
public class Common1Map : ClassMapping<Common1>
{
public Common1Map()
{
Id(x => x.Id, map => map.Generator(Generators.Native));
Property(x => x.Name);
}
}
}
namespace ConsoleApplication14
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using NHibernate.Hql.Ast;
using NHibernate.Linq;
using NHibernate.Linq.Functions;
using NHibernate.Linq.Visitors;
public class CalculatedPropertyGenerator<T, TResult> : BaseHqlGeneratorForProperty
{
public static void Register(ILinqToHqlGeneratorsRegistry registry, Expression<Func<T, TResult>> property, Expression<Func<T, TResult>> calculationExp)
{
registry.RegisterGenerator(ReflectionHelper.GetProperty(property), new CalculatedPropertyGenerator<T, TResult> { _calculationExp = calculationExp });
}
private CalculatedPropertyGenerator() { }
private Expression<Func<T, TResult>> _calculationExp;
public override HqlTreeNode BuildHql(MemberInfo member, Expression expression, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
{
return visitor.Visit(_calculationExp);
}
}
}
namespace ConsoleApplication14
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Cfg.MappingSchema;
using NHibernate.Dialect;
using NHibernate.Driver;
using NHibernate.Tool.hbm2ddl;
using NHibernate.Mapping.ByCode;
using NHibernate.Mapping;
using Iesi.Collections.Generic;
using System.Reflection;
using NHibernate.Linq.Functions;
using NHibernate.Linq;
public class SessionProvider
{
private static ISessionFactory sessionFactory;
public static SessionProvider Instance { get; private set; }
//DefaultLinqToHqlGeneratorsRegistry registry = new DefaultLinqToHqlGeneratorsRegistry();
ILinqToHqlGeneratorsRegistry registry = new DefaultLinqToHqlGeneratorsRegistry();
static SessionProvider()
{
var provider = new SessionProvider();
provider.Initialize();
Instance = provider;
}
private SessionProvider() { }
private void Initialize()
{
const string connString = "server=(local)\\mssql2008;database=Common;integrated security=sspi";
Configuration configuration = new Configuration();
configuration
.DataBaseIntegration(db =>
{
db.ConnectionString = connString;
db.Dialect<MsSql2008Dialect>();
db.Driver<SqlClientDriver>();
db.LogSqlInConsole = true;
db.IsolationLevel = System.Data.IsolationLevel.ReadCommitted;
})
.AddDeserializedMapping(GetMappings(), null);
CalculatedPropertyGenerator<Common1, string>.Register(registry, x => x.Display, Common1.CalculatedDisplayExpression);
// registry.RegisterGenerator(ReflectionHelper.GetProperty<Common1, string>(x => x.Display), new CalculatedPropertyGenerator());
var exporter = new SchemaExport(configuration);
exporter.Execute(true, true, false);
sessionFactory = configuration.BuildSessionFactory();
}
private HbmMapping GetMappings()
{
ModelMapper mapper = new ModelMapper();
mapper.AddMappings(Assembly.GetAssembly(typeof(Common1Map)).GetExportedTypes());
HbmMapping mappings = mapper.CompileMappingForAllExplicitlyAddedEntities();
return mappings;
}
public ISession OpenSession()
{
return sessionFactory.OpenSession();
}
}
}
Client:
namespace ConsoleApplication14
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate;
using NHibernate.Linq;
using NHibernate.Linq.Functions;
public class Tester
{
private ILinqToHqlGeneratorsRegistry registry = new DefaultLinqToHqlGeneratorsRegistry();
public void Go()
{
using (ISession session = SessionProvider.Instance.OpenSession())
{
CreateData(session);
IQueryable<ICommon> commons = session.Query<ICommon>();//.Where(x => x.Display.Contains("Common1 #7"));
var common1 = session.Query<Common1>().Where(x => x.Display.Contains("Common1 #7"));
foreach(var common in commons)
{
Console.WriteLine(common.Display);
}
}
}
private void CreateData(ISession session)
{
using (ITransaction tx = session.BeginTransaction())
{
for (int i = 0; i < 10; i++)
{
session.SaveOrUpdate(new Common1() { Name = "Common1 #" + i });
}
tx.Commit();
}
}
}
}
Register in SessionProvider class, like
configuration.LinqToHqlGeneratorsRegistry<MyLinqToHqlGeneratorsRegistry>();
MyLinqToHQLGeneratorRegistry implementation looks like this
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NHibernate.Linq.Functions;
using NHibernate.Linq;
namespace ConsoleApplication14
{
public class MyLinqToHqlGeneratorsRegistry : DefaultLinqToHqlGeneratorsRegistry
{
public MyLinqToHqlGeneratorsRegistry()
: base()
{
CalculatedPropertyGenerator<Common1, string>.Register(this, x => x.Display, Common1.CalculatedDisplayExpression);
}
}
}
You need to derive a class from DefaultLinqToHqlGeneratorsRegistry. Add the registration logic in its constructor (passing 'this' to CalculatedPropertyGenerator<>.Register()). Then register the class with the NHibernate configuration using:
cfg.LinqToHqlGeneratorsRegistry<OurLinqFunctionRegistry>();

why my first WCF Server doesn't work (wrong value returned to client)

This is my first WCF Server:
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
namespace Myns.MBClient
{
[ServiceContract]
public interface IManagementConsole
{
[OperationContract]
ConsoleData GetData(int strategyId);
}
[ServiceContract]
public class ConsoleData
{
private int currentIndicator;
[OperationContract]
public double GetCurrentIndicator()
{
return currentIndicator;
}
public void SetCurrentIndicator(int currentIndicator)
{
this.currentIndicator = currentIndicator;
}
}
class ManagementConsole : IManagementConsole
{
public ConsoleData GetData(int strategyId)
{
ConsoleData data = new ConsoleData();
data.SetCurrentIndicator(33);
return data;
}
}
}
In client I just call pipeProxy.GetData(0).GetCurrentIndicator()
Why program prints 0 while it supposed to print 33?
Client code (which I think has no problems):
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel;
using System.Text;
using Commons;
using myns.MBClient;
namespace myns.MBClientConsole
{
class Program
{
static void Main(string[] args)
{
ChannelFactory<IManagementConsole> pipeFactory =
new ChannelFactory<IManagementConsole>(
new NetNamedPipeBinding(),
new EndpointAddress(
"net.pipe://localhost/PipeMBClientManagementConsole"));
IManagementConsole pipeProxy =
pipeFactory.CreateChannel();
while (true)
{
string str = Console.ReadLine();
Console.WriteLine("pipe: " +
pipeProxy.GetData(0).GetCurrentIndicator());
}
}
}
}
If you create your own complex type to use with WCF you have to add a DataContract attribute instead of a ServiceContract, and you should use fields/properties that are decorated with DataMember. And do yourself a favor and use plain DTOs (DataTransferObjects - Objects with only fields/properties but no behavior):
[DataContract]
public class ConsoleData
{
[DataMember]
public int CurrentIndicator {get;set;}
}
You can find more on this here

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