Ninject and XML configuration Binding - c#

i have been searching the internet for any sample or getting start article on how to do binding with Ninject using XML extension but i couldnt find any help ! ,
can any body provide me with a very small sample on how can i do that ?
thanks in advance

I can't find any examples either, but honestly the source code is very small - I would just download (here) and read through the test cases.
The unit test project has some examples, like this:
<module name="basicTest">
<bind name="melee"
service="Ninject.Extensions.Xml.Fakes.IWeapon, Ninject.Extensions.Xml.Test"
to="Ninject.Extensions.Xml.Fakes.Sword, Ninject.Extensions.Xml.Test" />
<bind name="range"
service="Ninject.Extensions.Xml.Fakes.IWeapon, Ninject.Extensions.Xml.Test"
to="Ninject.Extensions.Xml.Fakes.Shuriken, Ninject.Extensions.Xml.Test" />
</module>
It doesn't seem to be very powerful. As someone else pointed out, the point of NInject is to 'free yourself from XML'.

Their only documentation shows what the xml config looks like but they don't give an example of how to load it so here is a simple example which shows both pieces of the puzzle.
Xml Config
This would be in a file called NinjectModules.xml. For it to find the type, I had to give it the assembly qualified name, even though everything was in a single .exe.
<module name="SomeModule">
<bind
service="Birds.IOwl, Birds, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
to="Birds.SlowOwl, Birds, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</module>
Loading Config
IKernel kernel = new StandardKernel();
kernel.Load("c:\path\to\NinjectModules.xml");
IOwl owl = kernel.Get<IOwl>();
owl.Fly();

After lost my saturday and review the Ninject.Extensions.Xml Source, I solve my problem:
(...)
var settings = new NinjectSettings { LoadExtensions = false };
kernel = new StandardKernel(settings, new XmlExtensionModule());
kernel.Load(#"C:\DEV\FSENQUETE\invista.xml");
//kernel.GetModules().Count() --> Ok! Result 34 modules... :)

Got the Solution:
Don't forget to set the Copy to Output of your xml file
Directory property of this file to Copy if newer, so that it can be copied to the
output directory automatically.
for more, see this PDF

Related

AppDomain.CurrentDomain.SetupInformation.PrivateBinPath is null

When I start my application that only has one AppDomain, AppDomain.CurrentDomain.SetupInformation.PrivateBinPath is null. Even though I have probing paths set in MyApp.exe.config as shown below.
I would have expeceted that AppDomain.CurrentDomain.SetupInformation.PrivateBinPath contains the string "Dir1;Dir2;Dir3".
How can I access the probing path as configured in the MyApp.exe.config?
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<appSettings>
<add key="Foo" value="Bar" />
</appSettings>
<startup>
<!-- supportedRuntime version="v1.1.4322" / -->
</startup>
<runtime>
<gcConcurrent enabled="true" />
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<publisherPolicy apply="yes" />
<!-- Please add your subdirectories to the probing path! -->
<probing privatePath="Dir1;Dir2;Dir3" />
</assemblyBinding>
</runtime>
<system.windows.forms jitDebugging="true" />
</configuration>
Update
As Hans Passant pointed out the comment below, SetupInformation.PrivateBinPath is not set for the primary appdomain. So the above doesn't work. What would be your suggestion to simulate the way fusion searches for assemblies in the probing path or at least take <probing privatePath="" /> from the current application configuration into account? The best thing I can come up with is to read <probing privatePath="" /> from App.config manually when the current domain is the primary appdomain (AppDomain.CurrentDomain.IsDefaultAppDomain() is true). Is there a better way?
Update 2
Here some additional background information what this is needed for: This problem occured in AppDomainAssemblyTypeScanner.GetAssemblyDirectories() of the Nancy framework.
Nancy autodiscovers and loads 3rd party modules and other "plugins". By default this is supposed to be done same way as normally linked assemblies would be loaded (i.e. as fusion would do it) by looking through the probing paths. Assemblies are loaded using Assembly.Load (as opposed to Assembly.LoadFrom) so as I understand it, all the dependent assemblies of the loaded assemblies must be reachable in the probing path of the application/appdomain too.
How can I access the probing path as configured in the MyApp.exe.config
To remain compatible what fusion will do, you can read the config file in effect to get the current probing paths:
private static string GetProbingPath()
{
var configFile = XElement.Load(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
var probingElement = (
from runtime
in configFile.Descendants("runtime")
from assemblyBinding
in runtime.Elements(XName.Get("assemblyBinding", "urn:schemas-microsoft-com:asm.v1"))
from probing
in assemblyBinding.Elements(XName.Get("probing", "urn:schemas-microsoft-com:asm.v1"))
select probing)
.FirstOrDefault();
return probingElement?.Attribute("privatePath").Value;
}
Supposing the config file sample in your question it returns:
"Dir1;Dir2;Dir3"
Not an answer, did not fit as a comment
As said above, default appdomain doesn't use AppDomainSetup for path probing config.
Instead of this the probing path is read from .appconfig file and is not exposed into managed code.
* self-hosted app on the full clr can override the behavior with custom ICustomAppDomainManager (or IHostAssemblyManager) but that's out of scope of the question.
So there're only three approaches possible:
First, you can call Nancy.Bootstrapper.AppDomainAssemblyTypeScanner.LoadAssemblies(somedir, "*.dll") by yourself
Second, you can wrap nancy host into secondary appdomain with custom private bin path set.
Third: wait for https://github.com/NancyFx/Nancy/pull/1846 and use custom IResourceAssemblyProvider.
In any case you'll need the list of assembly' directories. If you do not want to store the copy as <appSettings> value you'll had to parse the appconfig file by yourself.
I've always found that the easiest thing to do is intercept the AppDomain.AssemblyResolve event. Then you can load whatever assembly you want from wherever you want and return it. You can still store your settings in the appConfig...You could even probing path section if you particularly want to use it. One thing to note is that assemblies loaded using Assembly.Load don't end up in the same load context as assemblies loaded under the default load context (https://msdn.microsoft.com/en-us/library/dd153782(v=vs.110).aspx). This has the effect of changing how type and assembly resolution occurs for subsequent resolutions (after the initial call to Assembly.Load). Accordingly, you may want to intercept AppDomain.TypeResolve as well as AssemblyResolve...and you'll want to cache the Assemblies you load from AssemblyResolve...otherwise subsequent resolutions MAY actually load the same assembly again (depending on how exactly you call Assembly.Load)
If this is a problem of assemblies not loading, one method I've found to work effectively is to use the AppDomain.AssemblyResolve event which is fired whenever the appdomain fails to load an assembly...
Working with AppDomain.AssemblyResolve event
e.g.
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(LoadManually);
private Assembly LoadManually(object sender, ResolveEventArgs args)
{
....
return Assembly.LoadFrom(whereEverYouLike);
}
Inspired by g.pickardou's solution, I have created function without necessity to reference System.Xml.Linq:
private static string GetProbingPath()
{
var xmlDoc = new XmlDocument();
xmlDoc.Load(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
var privatePathAttribute = xmlDoc.SelectSingleNode("/*[name()='configuration']/*[name()='runtime']/*[name()='assemblyBinding']/*[name()='probing']/#privatePath");
return (privatePathAttribute as XmlAttribute)?.Value;
}

Replace #ifdefs in C# DLL

I have a C++ DLL which has #defines used like (these defines are automatically defined based on the build configuration, e.g. Debug, Release, etc)
#if defined(CONSTANT)
..
// Some code
#else
// Some other code
I need same functionality in C# dll.
Is it ok if I define some global constants in C# dll and use them
instead of defines?
e.g.
if(Globals.SomeConstant == SOMEVALUE)
// Do this
else
// Do smth else
Then when I want to ship the DLL I will in advance (probably as a default value during declaration) assign SOMEVALUE to Globals.SomeConstant - will this work this way? (Depending on which configuration I need).
I saw some similar questions but they weren't about DLLs.
You can use it similarly as in c++
You can define / undefine them in your source code or as a conditional compilation symbol. In visual studio this can be done using Solution Explorer - Properties - Build - conditional compilation symbols
However, nowadays people tend to use a configuration file for these constants. This way, you don't have to recompile your source code nor redistribute it to change the behaviour.
The most easy method is via visual studio solution explorer - properties - settings
You can add settings for most types. Booleans come closest to #define. Using an int can give you more than two possibilities. See the difficulties if you wanted to be able to use several values for a TimeSpan or an URI using #define.
The nice thing about using the settings is that a class is generated for you to easily access the settings.
Another method is to read the config file directly using the System.Configuration.ConfigurationManager class. This gives you more freedom about the format of the configuration. The disadvantage is that you have to convert the read values into proper types yourself, inclusive handling errors if the value can't be read.
Summarized: advantages of the config file method:
No need to change source files
No need to recompile
No need to re-install
only change the config file on those machines that need the change
improved type safety
My previous answer lead to a more questions than it answered. Hence I thought an example would help.
Suppose I have a DLL, called MyDll. It has a configuration setting that in really old times would have been defined using #define.
My C-synctax is a bit rusty, but it would look like:
#define UseAlternateGreeting
public class MyClass
{
public string GetGreeting()
{
#if defined UseAlternateGreeting
return "Hello World!";
#else
return "Here I am!";
#endif
}
}
Now suppose we have several programs that use this DLL. Program! wants to use the default setting. However Program2 wants to use the alternate setting. There is no way to solve this.
Besides if we want to change the value of the setting we have to recompile and redistribute everything to everyone.
Wouldn't it be easier if we could just edit a file with notepad to change the string?
Luckily Microsoft also saw the advantage of this. Over more than 10 years we have the idea of configuration files. Assemblies have a config file with the name of the application and the extension config. This file can easily be edited using any text editor by those who know what the configuration items mean.
If we replace the #define with an item in the config file the greeting could be changed to the alternate greeting without having to recompile and redistribute the whole program.
Luckily Visual Studio helps us a lot when creating the config file.
Preparations
Let Visual Studio Create a console application in a new Solution: name the program ConfigExample
Add a new Library to this application, name it MyDll
View the properties of MyDll
Add a Setting.
Name: MySetting,
Type: string,
Scope: application,
Value: Hello World! (without string quotes)
In project MyDll create a class MyClass
public class MyClass
{
public string GetText()
{
return Properties.Settings.Default.MySetting;
}
}
Go to project ConfigExample
Project Add reference to MyDll (via tab page solution)
Use the code in your main:
using MyDll;
static void Main(string[] args)
{
var obj = new MyClass();
var txt = obj.GetText();
Console.WriteLine(txt);
}
Compile and run, and you'll see the proper text displayed. If you go to the debug / bin directory of the program you'll find a text file ConfigExample.config. Open it in a text editor and you'll see... nothing abut hello world!
This means that your program is not really interested in a special setting, the setting that was default the time that MyDll was built may be used.
However, if you want to use a special setting,
In visual Studio, Go to project MyDll
open file app.config
a.o. you'll find the following
(to prevent the editor interfering with the formatting, I added an apostrophe to each line)
'</configSections>
'<applicationSettings>
'<MyDll.Properties.Settings>
'<setting name="MySetting" serializeAs="String">
'<value>Hello World!</value>
'</setting>
'</MyDll.Properties.Settings>
'</applicationSettings>
Copy paste this part to ConfigExample.Config
for all already distributed programs do this in the folder where the executable is (in your case: debug/bin)
for all ConfigExample programs that will be built in the future do this in visual studio in App.Config of the ConfigExample project.
The result will be as follows:
'<?xml version="1.0" encoding="utf-8" ?>
'<configuration>
' <configSections>
' <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="MyDll.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
' </sectionGroup>
' </configSections>
' <applicationSettings>
' <MyDll.Properties.Settings>
' <setting name="MySetting" serializeAs="String">
' <value>Hello World!</value>
' </setting>
' </MyDll.Properties.Settings>
' </applicationSettings>
'
' <startup>
' <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
' </startup>
'</configuration>
Now all we have to do is change the Hello World into an alternat greeting
' <MyDll.Properties.Settings>
' <setting name="MySetting" serializeAs="String">
' <value>Here I am!</value>
' </setting>
' </MyDll.Properties.Settings>
Run the program without building it and you'll see that the new value is used.
Advantages:
- It works with a lot of types that can be assigned from string - Type.IsAssignableFrom(typeof(string)). Visual Studio already supports a lot of types including TimeSpan and DateTime.
- You don't have to recompile your source code to change the value
- Several executables can use their own configuration setting: one program could use the original greeting, the other can use the alternate one
- If your program doesn't provide a value in the config file the default value is used.
- You don't have to read the configuration yourself.
- It is type safe: if you say it is a TimeSpan, then you have to do some serious typing to confuse it with for example an integer.
Well there is a lot more to be said about configuration, you can even have a configuration per user. But that's far outside your question about alternatives for plain C #define

Reading the System.Diagnostics.Debug window

I have a Netduino and it is currently outputting accelerometer data to the System. Diagnostics.Debug window. I am waiting on a USB->232 converter in the mail to properly get the data from the device into my app via a serial port but I was wondering just for quick testing purposes if anyone knows if it is possible to read the data from the Debug window back into my app?
EDIT - Solution:
I am posting this here for anyone who want my solution. I originally thought that Nuf's answer worked "Data written to System.Diagnostics.Debug can be captured with TraceListener class. MSDN has short tutorial how to set it up." but I found out that the Listener can only get data from within it's own application. Since I was using a Netduino, the Debug output was from a different program which meant the trace listener could not read it. So I found a way to read the text in the Output box directly.
Base on code from MSDN:
You will need to 3 references to your project. They are located in the .Net reference tab - EnvDTE, EnvDTE80, and extensibility.
using EnvDTE80;
using EnvDTE;
using Extensibility;
public static string ReadDebugBox()
{
EnvDTE80.DTE2 dte = (EnvDTE80.DTE2)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.10.0");
string data = "";
OutputWindow ow = dte.ToolWindows.OutputWindow;
OutputWindowPane owP;
TextDocument owPTxtDoc;
EditPoint2 strtPt;
owP = ow.OutputWindowPanes.Item("Debug");
owP.Activate();
owPTxtDoc = owP.TextDocument;
strtPt = (EditPoint2)owPTxtDoc.StartPoint.CreateEditPoint();
return strtPt.GetText(owPTxtDoc.EndPoint);
}
public static void ClearDebugBox()
{
EnvDTE80.DTE2 dte = (EnvDTE80.DTE2)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.10.0");
OutputWindow ow = dte.ToolWindows.OutputWindow;
OutputWindowPane owP;
TextDocument owPTxtDoc;
EditPoint2 strtPt;
owP = ow.OutputWindowPanes.Item("Debug");
owP.Activate();
owP.Clear();
}
There may be better ways of doing it but this is just one that worked for me so i thought I would share it.
Data written to System.Diagnostics.Debug can be captured with TraceListener class. MSDN has short tutorial how to set it up.
There are two ways to set this up, one way is to declaratively set this up in your app.config file. There's a lot of advantages to doing this such as not needing to recompile your application when changes are needed.
<configuration>
<system.diagnostics>
<trace autoflush="false" indentsize="4">
<listeners>
<add name="configConsoleListener"
type="System.Diagnostics.ConsoleTraceListener" />
</listeners>
</trace>
</system.diagnostics>
</configuration>
Alternatively, you can also do this inside of your code to output Debug traces to your application's console window.
Debug.Listeners.Add(new ConsoleTraceListener());

ReadOnlyNameValueCollection (reading from ConfigurationManager.GetSection)

Ok, so.....
<section name="test" type="System.Configuration.NameValueFileSectionHandler" />
<test>
<add key="foo" value="bar" />
</test>
var test = ConfigurationManager.GetSection("test");
So far so good. The debugger shows test contains one key, foo.
But GetSection returns object, so we need a cast:
var type = test.GetType();
// FullName: System.Configuration.ReadOnlyNameValueCollection
// Assembly: System
Ok, this should be simple enough. So....
using System;
var test = ConfigurationManager
.GetSection("test") as ReadOnlyNameValueCollection;
error!
The type or namespace ReadOnlyNameValueCollection does not exist in the namespace System.Configuration. Are you missing an assembly reference?
err... wtf?
A cast to System.Collections.Specialized.NameValueCollection gets the code working, but I don't really understand why the error.
And a search for ReadOnlyNameValueCollection on MSDN shows there is no documentation on this class at all. It doesn't seem to exist. Yet I have an instance of that type in my code.
System.Configuration.ReadOnlyNameValueCollection is an internal class to the System.dll assembly. So you can't refer to it from your code. It derives from System.Collections.Specialized.NameValueCollection, though, so that's why you're able to do that with the cast.

Registering generic types and services with Castle Windsor IoC

Hello again stackoverflowians,
I thought it was about time that I learnt how to use a DI framework. I've heard a lot of good things about Castle Windsor so I decided to go with that. Now there are PLENTY of tutorials out there on how to use it, however, I cannot find much useful information about what to do when Generics get involved. Here is my issue.
I have a BaseDAO
namespace Utilities.DataAccess
{
public class BaseDAO<T> : IBaseDAO<T>
{
public BaseDAO(IConnectionProvider _connectionProvider)
{
// Stuff
}
}
}
Im a little bit new to generics in this context and I have seen some tutorials which have a 'BaseDAO' with no generic declaration and simply the interface it implements with the generics on it. I have used the above way of doing things on many previous projects (without IoC) and its worked fine for me...anyways, onwards to the App.config !
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section
name="castle"
type="Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor"></section>
</configSections>
<castle>
<components>
<component
id="BaseDAO"
service="Utilities.DataAccess.Interfaces.IBaseDAO`1, Utilities.DataAccess"
type="Utilities.DataAccess.BaseDAO`1, Utilities.DataAccess" />
<component
id="NHibernateConnection"
service="Utilities.DataAccess.ConnectionProviders.IConnectionProvider, Finchtils"
type="Utilities.DataAccess.ConnectionProviders.NHibernateConnection" />
<component
id="XMLConnection"
service="Utilities.DataAccess.ConnectionProviders.IConnectionProvider, Finchtils"
type="Utilities.DataAccess.ConnectionProviders.XMLConnection, Utilities" />
</components>
</castle>
</configuration>
Now as some of you may of figured by now, this is a utility library. I intend to use this assembly for each project I create so that I don't have to write the same data access code which remains the same across all solutions. The implications of such of course is that I cannot tell castle exactly what type parameter I will pass to the BaseDAO, in one project it might be a Customer object, another entirely different. I have read on other forums that this is entirely possible as when you request the object from the container you can specify the type then like;
BaseDAO<Customer> baseDao = container.Resolve<BaseDAO<Customer>>();
Although it is against my design efforts, I have tried to use the following notation in the App.config
<component
id="BaseDAO"
service="Utilities.DataAccess.Interfaces.IBaseDAO`1[[Utilities.DataInterface.IEntity]], Finchtills.DataAccess"
type="Utilities.DataAccess.BaseDAO`1[[Utilities.DataInterface.IEntity]], Finchtils.DataAccess" />
However, this has not worked either, in any case I get the following error:
Utilities.Testing.DataAccess.Unit.Testing_BaseDAO (TestFixtureSetUp):
System.Exception : The type name Utilities.DataAccess.BaseDAO`1, Utilities.DataAccess could not be located.
----> System.IO.FileNotFoundException : Could not load file or assembly 'Utilities.DataAccess' or one of its dependencies. The system cannot find the file specified.
Reading this error, I think it could be one of two things:
I am missing something from the config file to do with the generics of the types and services.
I have named something incorrectly I.E an assembly name.
I have treated the assembly name as the project that item is contained within, in other words, at no point have i used <solution name>.<project name>.<item folder>.<item name> but merely started at the project level...I assume that any config option would know what solution it is being called from.
Thank you for any help you may be able to give on this subject.
The assembly name can be found in Visual Studio thus:
In the solution explorer, double-click the properties node
Open the Application tab
Assembly name is near the top right corner
Or, if you're compiling at the command line, you use the /out argument.
Also, you need to specify the assembly for the type arguments (inside the square brackets). So, assuming all your types are in the DataAccess assembly, and that the assembly is called (for brevity's sake) "DataAccess":
<component
id="BaseDAO"
service="Utilities.DataAccess.Interfaces.IBaseDAO`1[[Utilities.DataInterface.IEntity, DataAccess]], DataAccess"
type="Utilities.DataAccess.BaseDAO`1[[Utilities.DataInterface.IEntity, DataAccess]], DataAccess" />
But I agree with other commenters that it's better to do the registrations in code. You don't have to use the verbose type syntax, for one, and you get compiler checking of your types. There are some disadvantages, however: it's harder to tell if you have unused types because the registration call counts as using the type.

Categories