Archive for category Code
DI with Ninject for an MVC project
This seems to be a somewhat moving target with ASP.Net MVC moving up the versions as well as Ninject. This particular target will be ASP.Net MVC 2.0 and Ninject 2.0.
First set up the references:
- Download Ninject.Web.Mvc (If not using git, there is a download source link on the page).
- Open the mvc2/Ninject.Web.Mvc.sln and compile with release settings.
- Copy the files Ninject.dll and Ninject.Web.Mvc.dll from the mvc2/build/debug/release folder to the lib folder of your MVC project.
- Add references to these two files to your MVC project.
The DI Container (called a Kernel with Ninject) needs initializing on app startup which, with MVC, is in the Global.asax. Add the following using statements to the Global.asax:
using Ninject; using Ninject.Modules; using Ninject.Web.Mvc;
Change the MvcApplication so it inherits from NinjectHttpApplication:
public class MvcApplication : NinjectHttpApplication {
Let Visual Studio implement the CreateKernel method.
override the OnApplicationStarted method copying in the lines from the Application_Start method:
protected override void OnApplicationStarted() {
AreaRegistration.RegisterAllAreas();
RouteRegistrar.RegisterRoutes(RouteTable.Routes);
}
Then delete the Application_Start method.
Ninject stores the rules it uses to return class instances in Modules which are derived from NinjectModule. Add the following class to the MVC project:
using Ninject.Modules;
namespace MvcApp.Web {
public class WebModule : NinjectModule {
#region Instance Methods
public override void Load() {
}
#endregion
}
}
The Load method is where we specify how each request for a concrete class is fulfilled.
Lastly, modify the CreateKernel method so that the module is passed into the Kernel’s ctor:
protected override IKernel CreateKernel() {
var modules = new INinjectModule[]
{
new WebModule()
};
var kernel = new StandardKernel(modules);
return kernel;
}
Simple WCF Service Host
app.config
The configuration for a simple http WCF host is:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
</appSettings>
<system.serviceModel>
<services>
<service name="AssemblyNamespace.ServiceImplementation"
behaviorConfiguration="ServiceBehavior">
<endpoint address="ServiceName"
binding="basicHttpBinding"
contract="AssemblyNamespace.ServiceContractInterface" />
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://HostName:Port/"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
An example:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
</appSettings>
<system.serviceModel>
<services>
<service name="TestService.CalculatorService"
behaviorConfiguration="CalculatorServiceBehavior">
<endpoint address="CalculatorService"
binding="basicHttpBinding"
contract="TestService.ICalculator" />
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8000/"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="CalculatorServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
The Service
Define the service in an interface
using System.ServiceModel;
namespace TestService
{
[ServiceContract]
public interface ICalculator
{
#region Instance Methods
[OperationContract]
double Add(double n1, double n2);
[OperationContract]
double Divide(double n1, double n2);
[OperationContract]
double Multiply(double n1, double n2);
[OperationContract]
double Subtract(double n1, double n2);
#endregion
}
}
Then implement the interface
using System;
namespace TestService
{
public class CalculatorService : ICalculator
{
#region ICalculator Members
public double Add(double n1, double n2) {
double result = n1 + n2;
Console.WriteLine("Received Add({0},{1})", n1, n2);
Console.WriteLine("Return: {0}", result);
return result;
}
public double Divide(double n1, double n2) {
double result = n1/n2;
Console.WriteLine("Received Divide({0},{1})", n1, n2);
Console.WriteLine("Return: {0}", result);
return result;
}
public double Multiply(double n1, double n2) {
double result = n1*n2;
Console.WriteLine("Received Multiply({0},{1})", n1, n2);
Console.WriteLine("Return: {0}", result);
return result;
}
public double Subtract(double n1, double n2) {
double result = n1 - n2;
Console.WriteLine("Received Subtract({0},{1})", n1, n2);
Console.WriteLine("Return: {0}", result);
return result;
}
#endregion
}
}
The Host
Lastly create a host for the service
using System;
using System.ServiceModel;
namespace TestService
{
internal class Program
{
#region Class Methods
private static void Main() {
using (ServiceHost serviceHost = new ServiceHost(typeof (CalculatorService))) {
serviceHost.Open();
Console.WriteLine("The calculator service is ready.");
Console.WriteLine("Press <ENTER> to terminate service.");
Console.WriteLine();
Console.ReadLine();
}
}
#endregion
}
}
Simple Thread Safe Singleton
This is simple but should work:
public sealed class Singleton
{
private static Singleton _instance = new Singleton();
private Singleton() { }
public static Singleton Instance
{
get
{
return _instance;
}
}
}
As the CLR synchronises static constructors it is thread safe. Also static constructors are not called until the types is accessed to you have lazy instantiation (use nesting if there are other static methods).
How to Use InternalsVisibleTo
Posted by John in CSharp, Code, Visual Studio on June 18, 2007
VS2005 defaults new classes to internal rather than public (although it appears that Orcas defaults to public). This is good as it reduces the public interface of your assembly and it encourages you to actually think about whether a class needs to be public.
You can allow other assemblies access to your internal types and members though, by using the InternalsVisibleTo attribute. This is especially useful for allowing your test assembly to access your internal classes.
This attribute can only be applied to strongly named assemblies.
[assembly:InternalsVisibleTo("TestAssembly, PublicKey=TestAssembly’s public key")]
The attribute requires the assembly name and the public key. To retrieve the public key use sn.exe. Open a visual studio command prompt and enter:
sn.exe -Tp AssemblyPath
Alternatively if you use an alternate file explorer you could set up a macro.
How to Give an Assembly a Strong Name
Posted by John in CSharp, Code, Visual Studio on June 14, 2007
To Strongly name an assembly you need to associate it with a public and private key. This can be either done by the developer when they compile the assembly (signing) or by at a later stage for instance by the QA department (delayed signing).
Public and private keys can be associated with code signing certificates, generated using sn.exe, or they can be generated from within Visual Studio.
Open the project properties for the assembly you want to sign and check ‘sign the assembly’ on the signing tab. To create a key file, select New from the drop down and follow the directions or Browse for an existing key file. If you create a key file it is worth moving it from the bin directory as you should be using it across multiple projects.
Once compiled you will have a signed assembly with a strong name.