Archive Page 4 of 26

11AugFinally found the insert key on my macbook pro keyboard

I finally managed to figure out what the insert key is on my macbook pro. I missed it a lot because in Resharper the standard command to generate code is Alt+Ins. This key combination seems to be engraved in my brain because it was really hard for me to use it with a different key combination. Anyway the winning combinations are:

Insert: fn+return

Alt+Insert: fn + alt/option + return

07AugIronNails : Rails like development for IronRuby with WPF/Silverlight

For my book IronRuby I’m working on chapter 4. That chapter is about doing WPF development with IronRuby. I started out with a straight port of Witty to IronRuby. As I was doing that the cogs started turning and I came up with a way to bring the rails style of development to WPF.   I decided to investigate that route a little bit further and now I have a small framework that enables you to write WPF applications with the MVC paradigm. I decided to open that code up as open source and host it on github. 

At first I used the name Sails for my framework but it turns out there is java clone of rails that is called opensails. So to avoid confusion David M. Peterson proposed the name IronNails.

On Sat, 02 Aug 2008 08:00:44 -0600, Charles Oliver Nutter wrote:

    FYI, there’s already a framework named "Sails" for Java:
http://www.opensails.org/

For the sake of sticking to the "Iron" theme, why not replace the ‘S’ with an ‘N’ and go with IronNails. ;-)   Maybed it’s just me, but if given the choice, I’d much rather nail it than sail it any day of the week. :D


/M:D

M. David Peterson

You can find the project here: http://github.com/casualjim/ironnails

At this moment it’s definitely not finished at all, but it does work. The remainder of the week I’ll move my previous demo code onto this framework, update the code samples in my chapter and finish the content. I hope I will have all of this done by the end of next week.

Back to the IronNails project:

Because DLR objects cannot be used to bind to in WPF you have to define a skeleton of the ViewModel in C#, but this will change in the future. When that changes I’ll look at extending the framework to make use of some other WPF patterns like defining a DependencyObject and Behaviors. Once those are defined you get a very clean separation between design and behavior.

This is abstracted away from you but in the background the framework works with the View – ViewModel – Model – Controller pattern although I’ve tried to keep your exposure to the view model to a minimum. The framework follows naming conventions per language. So in C# and XAML you camel case stuff and in IronRuby you underscore stuff.

The very core of the framework is defined in C# but most of the code is IronRuby, depending on how hard it will be after the DLR RTM’s I may look at adding support for all the DLR languages.

IronNails
=========

IronNails is a framework inspired by the Rails and rucola frameworks. It offers a rails-like way of developing
applications with IronRuby and Windows Presentation Foundation (WPF).
This framework uses the pattern Model – ViewModel – View – Controller (M-VM-V-C). It should be able to run on both WPF
and Silverlight.
The idea is that the views can be created using a design tool like Blend for example and just save that xaml as is. The
designer should not need to use anything else than drag and drop to create a GUI design. The behaviors are then added to
the view by using predefined behaviors in the framework or by defining your own behavior.
The framework then generates a proxy for the view which will be used to transparently wire up the commands in the
behaviors to controller actions.

You are now able to write the following code for a controller:

class MyController < IronNails::Controller::Base

  view_action :show_message, :triggers => :my_button do
    MessageBox.show "This is the great message from a block"
  end

  view_action :change_color, :triggers => { :element => :my_text_block, :event => :mouse_enter }
  view_action :reset_color, :triggers => { :element => :my_text_block, :event => :mouse_leave } do |view|
    view.my_text_block.foreground = :black.to_brush
  end

  view_object :people, Person.find_all

  def change_color(view)
    view.my_text_block.foreground = :red.to_brush
  end

end

At this moment the project has 0 unit tests, it has below minimal documentation and it still needs a work like defining the behaviors. I have to move on with my book but intend to continue developing this framework after my book is finished and IronRuby RTM’s.  There are some more workarounds in the project that will all disappear as IronRuby progresses.

kick it on DotNetKicks.com

13JulMoving back to belgium

Tonight is my last night in New Zealand. Tomorrow I will fly back to Belgium to see what has changed in the 3 years that I’ve been away. I already know that my home city Antwerp has changed a lot because they were completely redoing the place when I left. I think it might still too soon for a reflective post on my experiences in New Zealand. What I can say is that I had a great time here and I made some great friendships with some extraordinary people. Depending on who you ask this is a good or bad thing but I’ll surely be back in a couple of years :)

Continue reading ‘Moving back to belgium’

12JulHow I Got Started in Software Development

Michael Eaton started a meme with the question: How did you get started in software development?

Yesterday Simone Chiaretta tagged me in his post, so it’s now my turn to answer the questions and tag other bloggers:

Continue reading ‘How I Got Started in Software Development’

12JunDynamic Script Control

Both Silverlight and WPF use XAML markup to describe their user interface.  As I’m currently writing my chapter on WPF for my book IronRuby In Action and I want to use some xaml that has been generated before for a different project but with an IronRuby class to load the xaml I’m in trouble. This is because you can declare assembly references in the xml namespace declarations so you can use the types in that assembly from xaml. 

The DLR based languages don’t compile into static assemblies and this means that you can’t use those xml namespace definitons to reference your assemblies.  I wrote a fairly trivial control that acts like a hook for DLR based controls in the XAML tree.

You can check it out at codeplex.
http://codeplex.com/dynamicscriptcontrol

The idea behind this control is that you can "hook" your DLR based control into the visual tree by setting some properties.  You can set properties on the DLR based control by setting the Attributes property on the DynamicScriptControl

Let’s look at a quick example:

1. The ruby file defining a custom TextBox. But you can do whatever  you want in that ruby file of course.

dynamic_script_control_rubyscript

All this textbox does is preset it’s text property to "I’m prefilled"

2. The xaml for the window

dynamic_script_control_window_xaml 

You first declare a namespace for the assembly that has the DynamicScriptControl. Next I have a StackPanel that contains 2 DynamicScriptControls. The first just contains the 2 mandatory properties. We need to know which class you want to instantiate in the file you provide by setting the ScriptFile property. This script file property is a path to your ruby file in my case prefilled_text_box.rb.
The second DynamicScriptControl is one where I want to initialize the control with my own text property. To declare those properties you have to add them to the Attributes collection of the DynamicScriptControl. At this moment it’s not smart enough to know which datatype you give it so you can specify a format string which was necessary in this case because text is a string.

3. The result

dynamic_script_control_window

Michael Foord the author of IronPython In Action will provide the python integration in this control.

There was a release of the Dynamic Silverlight SDK earlier this week which contained the necessary source code files to compile a common DLR for both IronRuby and IronPython.  That is what makes it possible to support multiple scripting languages from the start. 

I’ve hosted the source code on google and you can find that at:

http://code.google.com/p/dynamic-script-control

16MayThe IronRuby in Action book went into EAP today

It’s been a bit of journey but my IronRuby in Action book finally went into EAP today. EAP means exactly what it means in the software world, still very much subject to change. This could be seen as a public review :)   I welcome any suggestions you may have.

You can find the book at http://manning.com/carrero
There is also a forum there where you can post suggestions and/or problems you may encounter when running the code samples. I look at it as my issue tracker :)

I’m currently working on a chapter where I build a complete twitter client with IronRuby and WPF (not silverlight as indicated on the current TOC). It is based on Witty but uses IronRuby instead of C# to drive the xaml. Also some storyboards have been replaced by IronRuby instead of by xaml stuff. It’s also not a straight port of Witty because I haven’t really looked at their code apart from the xaml that is.

Happy reading :)

Update: Some people started calling it the “jugs book”

kick it on DotNetKicks.com

Technorati Tags: ,

13MayUsing the mini spec framework that comes with IronRuby

I’ve set out to build my first "real" application (still playground material) with IronRuby today and for me no application can be built without having the unit tests or specs to give me that warm fuzzy feeling that things should work. That being said the first thing on my list of things to do is figure out how to use the minispec framework that IronRuby currently uses to write my specs.

Since my application will be doing a fair bit of http requests I want to be able to mock that out so I don’t have to rely on the webservers to be up and running or being online to run the specs.

The first thing I did was copy a couple of files from the tests\IronRuby\Specs directory in the directory where you downloaded the IronRuby source code into (C:\tools\IronRuby) in my case. I copied those files in a specs subdirectory of my application directory. The files we’re going to need are:

  • mini_mock.rb
  • mini_rspec.rb
  • mspec_helper.rb
  • rspec_helper.rb
  • simple_mock.rb
  • spec_helper.rb
  • spec_runner.rb

The next thing on my to-do list is then to change some of the files so that we can run our own specs on our terms.

The first changes I made are in spec_helper.rb. I replace require ‘mini_mock’ on line 18 with require File.dirname(__FILE__) + ‘/mini_mock’

The next bit is in the spec_runner.rb file. I just removed the word core/ in that file because our specs will just live in a directory structure under the specs folder.

now to create the first spec and mock with that spec framework:

I created a folder models in my specs folder. In that folder I created a file spec_test_spec.rb with the following content

require File.dirname(__FILE__) + "/../spec_helper.rb"

describe "Specs" do

  it "should work" do
    # puts "Yay!!! It works"
  end

  it "should mock methods" do
    mock = Object.new
    mock.should_receive :mocked_method, :returning => "Yay!!! I'm mocking"
    result = mock.mocked_method
    result.should == "Yay!!! I'm mocking"
    # puts result
    Mock.verify
  end

end

This just has a test method to see if it will run the rspec syntax and the second is where I tested to see if I could mock methods on objects. In the future we’ll be able to use mocha and rspec for example and then we’ll have a nicer syntax for mocking stuff.  But this will do for now.

Then I opened up a command console and navigated to the folder that contains my application

+ C:\projects\lumpr\src\Sylvester.DesktopEdition\Sylvester.IronRuby\specs

» ir spec_runner.rb models – pass

Specs should work

Specs should mock methods

Total pass: 2 out of 2 examples

I may post an example later this week with some real tests but this shows you how to get going with the mini spec framework to test your .NET stuff today.

Technorati Tags: ,

23AprTaking Ninject to new places

When I started looking at Ninject I was pretty impressed by how nice the code looks and how well the project has been put together. Nate had been profiling the project yesterday and it performs slightly better than its cousin from the Castle framework but that difference is almost negligible.
However I recommend you download the Ninject framework and just look at its codebase because it may teach you some new tricks or give you some new insights. The rest of this post will explain a small MVP framework for Ninject and WPF that I added to Ninject contrib last weekend.

Continue reading ‘Taking Ninject to new places’

18AprNinject (Part 2): Customizing your infrastructure for logging

Yesterday we had a little introduction to Ninject. Today I’d like to examine what’s involved in getting some AOP style logging going for your application. I find that there are only very few places where I’m logging something that steps out of the bounds of being called at the end of the method when things succeed. I’m generally more interested in what happens when things go wrong and that’s when I log the exception. In some cases I’ll be  interested in the actual parameters.

The code I’m going to show you will take care of basic logging needs but if you want more information about what happens inside your method you’re either going to need to extend my implementation or log the call from within your method body.  We’re going to implement logging that when run with the debug level turned on will tell us that a method is going to execute, whether it finished successfully or with an error and if there was an error it will also log the exception. 

To get this thing on the road, on the LightSpeed road that is. We’re going to use NLog to get flexible routing of log messages. We’re first going to create a LightSpeedTarget that is a customized NLog target (route destination) for your log messages.

namespace LoggingDemo.UI.Integration
{
    ///

    /// This class represents a NLog target that we can reference in the NLog.config file
    /// You can use this to use Lightspeed to log to the database just like a file target etc.
    /// 

    [Target("LightSpeedTarget")]
    public class LightSpeedTarget : TargetWithLayout
    {

        public LightSpeedTarget(){
            Layout = "${message}";
        }

        protected override void Write(LogEventInfo logEvent)
        {
            var logMessage = CompiledLayout.GetFormattedMessage(logEvent);

            var appEvent = new ApplicationEvent
            {
                Sequence = logEvent.SequenceID,
                EventTime = logEvent.TimeStamp,
                Level = logEvent.Level.Name,
                LoggerName = logEvent.LoggerName,
                Message = logMessage
            };

            if (logEvent.Exception != null) appEvent.Exception = logEvent.Exception.ToString();
            if (logEvent.StackTrace != null) appEvent.StackTrace = logEvent.StackTrace.ToString();
            if (logEvent.UserStackFrame != null) appEvent.UserStackFrame = logEvent.UserStackFrame.ToString();

            Repository.Add(appEvent);
            Repository.CompleteUnitOfWork();
        }
    }
}

The class above overrides the TargetWithLayout class from the NLog project. The attribute tells NLog how to find this target. In the constructor I override the default message layout because it was a bit too verbose to my liking.

We then override the Write method where we map the properties to our ApplicationEvent. And lastly we add the event to the repository and commit it.

Now if we want our application to use this we’re going to have to tell it how. Nlog does this by looking for an nlog.config file in your application directory.  So let’s go ahead and add an nlog.config file to our project. I’ll show you the nlog.config file for the application. In my unit test project I’m using the console logger so I can see what’s going on :)

The NLog.config file for the application:

image

My NLog.config file for my test project:

 image

This enables our application to use the target we just created. Moving on now to the Interceptor which is Ninject specific (You can do the same with other DI frameworks).  In Ninject you can tell the kernel to intercept a method on a class and execute some logic before and after invocation of the method. We can tell Ninject to intercept all methods on a class, specific methods or when we say all methods we can still exclude some of them. For our logging example I chose to use all methods on a class. You can do this by decorating the class with an [Intercept] attribute. If you would want a method not to be intercepted you can by decorating that method with an [DoNotIntercept] attribute.

I took the liberty of inheriting of that attribute first.. that makes the rest of my code look a little bit prettier.

The LogMyCallsAttribute:

using Ninject.Core;

namespace LoggingDemo.UI.Interceptors
{
    public class LogMyCallsAttribute : InterceptAttribute
    {
        public LogMyCallsAttribute() : base(typeof(LoggingInterceptor))
        {
        }
    }
}

The LoggingInterceptor:

using System;
using Ninject.Core.Interception;
using Ninject.Core.Logging;

namespace LoggingDemo.UI.Interceptors
{
    public class LoggingInterceptor : SimpleFailureInterceptor
    {
        private readonly ILogger _logger;
        private bool _hasError;

        public LoggingInterceptor(ILogger logger)
        {
            _logger = logger;
            _hasError = false;
        }
        protected override void BeforeInvoke(IInvocation invocation)
        {
            _logger.Debug("About to invoke {0}", MethodNameFor(invocation));
        }

        protected override void OnError(IInvocation invocation, Exception exception)
        {
            _logger.Error(exception, "There was an error invoking {0}.\r\n", MethodNameFor(invocation));
            _hasError = true;
            base.OnError(invocation, exception);
        }

        protected override void AfterInvoke(IInvocation invocation)
        {
            _logger.Debug("invocation of {0} finished {1}.", MethodNameFor(invocation), (_hasError ? "with an error state" : "successfully"));
        }

        private static string MethodNameFor(IInvocation invocation)
        {
            return invocation.Request.Method.Name;
        }
    }
}

This class only overrides a couple of callbacks from its base class the SimpleFailureInterceptor. This is where the actual interception takes place.

using System;
using Ninject.Core;
using Ninject.Core.Interception;

namespace LoggingDemo.UI.Interceptors
{
    public abstract class SimpleFailureInterceptor : IInterceptor
    {

        #region IInterceptor Members

        public virtual void Intercept(IInvocation invocation)
        {
            try
            {
                BeforeInvoke(invocation);
                invocation.Proceed();
            }
            catch (Exception ex)
            {
                OnError(invocation, ex);
            }
            finally
            {
                AfterInvoke(invocation);
            }
        }

        #endregion

         protected virtual void BeforeInvoke(IInvocation invocation)
        {
        }

        protected virtual void AfterInvoke(IInvocation invocation)
        {
        }

        protected virtual void OnError(IInvocation invocation, Exception exception)
        {
            throw exception;
        }
    }
}

This is al the work that is involved in the actual implementation of our logger. Now I’d like to get some confirmation that things actually do work.  Unit testing to the rescue I’d say ;)  

The first thing we’re going to need is way to verify that stuff actually got intercepted. I did that by subclassing the LoggingInterceptor with a LoggingCounterInterceptor in my unit test project.

    public class LoggingCounterInterceptor : LoggingInterceptor
    {
        public int Count { get; private set; }

        public int ErrorCount { get; private set; }

        public void Reset()
        {
            Count = ErrorCount = 0;
        }

        public LoggingCounterInterceptor(ILogger logger) : base(logger)
        {
        }

        protected override void BeforeInvoke(Ninject.Core.Interception.IInvocation invocation)
        {
            Count++;
            base.BeforeInvoke(invocation);
        }

        protected override void OnError(Ninject.Core.Interception.IInvocation invocation, System.Exception exception)
        {
            ErrorCount++;
            base.OnError(invocation, exception);
        }
    }

    //The attribute for testing
    public class LogMyCallsCounterAttribute : InterceptAttribute
    {
        public LogMyCallsCounterAttribute() : base(typeof(LoggingCounterInterceptor))
        {
        }
    }

In the code above we’re just adding 2 counter properties to the interceptor and adding their counts at the appropriate time. Next we’re going to need some kind of service class or something on which we can use our interceptor, enter the InterceptedServiceMock.

    public interface IInterceptedServiceMock
    {
        void MethodWithoutBody();
        void MethodThatThrowsAnException();
    }

    [LogMyCallsCounter]
    public class InterceptedServiceMock : IInterceptedServiceMock
    {
        public virtual void MethodWithoutBody()
        {
            // Nothing to do here
        }

        public virtual void MethodThatThrowsAnException()
        {
            throw new Exception("Because I can.");
        }
    }

The code above has one method that should execute and one method that throws an exception so we can verify things get picked up accordingly. Now all that’s left to do is write the appropriate specs for them and see if they pass :)

    [Context(Description = "Specifies the behavior for the LogMyCallsInterceptor")]
    public class LogMyCallsInterceptorSpec
    {
        private IKernel _kernel;

        [BeforeEach]
        public void Before()
        {
            var inlineModule = new InlineModule(m => m.Bind<IInterceptedServiceMock>().To<InterceptedServiceMock>());

            _kernel = new StandardKernel(new LinFuModule(), new NLogModule(), inlineModule);
        }

        [AfterEach]
        public void After()
        {
            _kernel.Dispose();
        }

        [Specification("All this should do is show the calls in the test runner. It should log to the console")]
        public void ShouldShowCallsInConsole()
        {
            var service = _kernel.Get<IInterceptedServiceMock>();
            IContext context = new StandardContext(_kernel, typeof(IInterceptedServiceMock));

            IRequest request = new StandardRequest(
                context,
                service,
                typeof(InterceptedServiceMock).GetMethod("MethodWithoutBody"),
                new object[0]
            );

            var interceptors = _kernel.GetComponent<IInterceptorRegistry>().GetInterceptors(request);

            var enumerator = interceptors.GetEnumerator();
            enumerator.MoveNext();

            Specify.That(interceptors.Count).Must.Equal(1, "There should be 1 interceptor registered");
            Specify.That(enumerator.Current).Must.Be.InstanceOf(typeof(LoggingCounterInterceptor));

            var interceptor = enumerator.Current as LoggingCounterInterceptor;

            service.MethodWithoutBody();

            Specify.That(interceptor).Must.Not.Be.Null();
            Specify.That(interceptor.Count).Must.Equal(1, "There should be 1 invocation counted.");
        }

        [Specification("Should show valid counts for a number of invocations")]
        public void Should_Show_Correct_Counts_For_Number_Of_Invocations()
        {
            var service = _kernel.Get<IInterceptedServiceMock>();
            IContext context = new StandardContext(_kernel, typeof(IInterceptedServiceMock));

            IRequest request = new StandardRequest(
                context,
                service,
                typeof(InterceptedServiceMock).GetMethod("MethodWithoutBody"),
                new object[0]
            );

            var interceptors = _kernel.GetComponent<IInterceptorRegistry>().GetInterceptors(request);

            var enumerator = interceptors.GetEnumerator();
            enumerator.MoveNext();

            Specify.That(interceptors.Count).Must.Equal(1, "There should be 1 interceptor registered");
            Specify.That(enumerator.Current).Must.Be.InstanceOf(typeof(LoggingCounterInterceptor));

            var interceptor = enumerator.Current as LoggingCounterInterceptor;

            service.MethodWithoutBody();
            service.MethodWithoutBody();
            service.MethodWithoutBody();

            Specify.That(interceptor).Must.Not.Be.Null();
            Specify.That(interceptor.Count).Must.Equal(3, "There should be 3 invocations counted.");
            Specify.That(interceptor.ErrorCount).Must.Equal(0, "There should be no errors counted.");
        }

        [Specification("Should have the correct count of invocations and the correct error count.")]
        public void Should_Have_Correct_Invocation_And_Error_Count()
        {
            var service = _kernel.Get<IInterceptedServiceMock>();
            var context = new StandardContext(_kernel, typeof(IInterceptedServiceMock));

            var request = new StandardRequest(
                context,
                service,
                typeof(InterceptedServiceMock).GetMethod("MethodWithoutBody"),
                new object[0]
            );

            var errorRequest = new StandardRequest(
                context,
                service,
                typeof (InterceptedServiceMock).GetMethod("MethodThatThrowsAnException"),
                new object[0]
            );

            var interceptors = _kernel.GetComponent<IInterceptorRegistry>().GetInterceptors(request);
            var errorInterceptors = _kernel.GetComponent<IInterceptorRegistry>().GetInterceptors(errorRequest);

            var enumerator = interceptors.GetEnumerator();
            enumerator.MoveNext();
            var errorEnumerator = errorInterceptors.GetEnumerator();
            errorEnumerator.MoveNext();

            Specify.That(interceptors.Count).Must.Equal(1, "There should be 1 interceptor registered");
            Specify.That(enumerator.Current).Must.Be.InstanceOf(typeof(LoggingCounterInterceptor));
            Specify.That(errorInterceptors.Count).Must.Equal(1, "There should be 1 error interceptor registered");
            Specify.That(errorEnumerator.Current).Must.Be.InstanceOf(typeof(LoggingCounterInterceptor));

            var interceptor = enumerator.Current as LoggingCounterInterceptor;
            var errorInterceptor = errorEnumerator.Current as LoggingCounterInterceptor;

            service.MethodWithoutBody();
            service.MethodWithoutBody();
            service.MethodWithoutBody();

            try
            {
                service.MethodThatThrowsAnException();
            }
            catch
            {
            }

            Specify.That(interceptor).Must.Not.Be.Null();
            Specify.That(interceptor.Count).Must.Equal(3, "There should be 3 invocations counted.");
            Specify.That(errorInterceptor.Count).Must.Equal(1, "There should be 1 invocation counted.");
            Specify.That(errorInterceptor.ErrorCount).Must.Equal(1, "There should be 1 error counted.");
        }
    }

Testing this got a little messy I have to admit that. Now for a concrete example of how that looks in my application:

    [Service(typeof(IBlogService))]
    [LogMyCalls]
    public class BlogService : DataServiceBase<Blog>, IBlogService

And that’s how I implemented logging for my application :) Needless to say it was the testing that took me the longest to write. And from now on I don’t have to worry anymore about forgetting that logger call. I always have minimal logging going. AOP is usefull in a lot more cases but this seemed like a good and easy example.

Our next post will deal with initializing the modules in your application and their respective behaviors.

kick it on DotNetKicks.com

17AprNinject: Getting all the stuff you’ll need

I have a new project I started and I could reevaluate my toolset :) I decided to take a closer look at Ninject, Moq and NSpecifyMoq has been talked about enough I think, a really nice way of mocking and I will definitely be using more of it. My original plan was to write one big blog post.. but it is going to be far too long, so I’m breaking it up in smaller bite size pieces.

What I did was download the code, have it rest on my pc for about a week, updated again when I really got round to using it. I read the wiki which gives a short introduction on what’s what in Ninject and everybodies jobs. Decided that the wiki was cool for some more theoretical knowledge but I really needed to see more code.

I opened the project and something rare happened: I was actually very happy with the code I found, not always the case I can tell you ;) .  Anyway the gold is in the unit tests, it’s got great test coverage and it shows lots of the possibilities of Ninject. It’s like a great big manual for you to get really advanced with it really quickly.  I was slightly disappointed to see that there was no NLog support for Ninject, that disappointment quickly turned in to joy when I figured out it only took me 20 minutes to plug NLog in. And it was added to the trunk the same day.

Now I don’t want to make this post about which DI framework is better Windsor, Spring, Structuremap or Ninject. I just know that Ninject and I will become good friends over the next couple of months I like it. Ninject outsources its proxy generation to either Castle’s DynamicProxy2 or to LinFu DynamicProxy.  LinFu seemed like an interesting choice after reading this codeproject article. It’s supposedly faster than castle’s dynamic proxy. Luckily Ayende is there to put this in perspective. And I can confirm that the error messages etc castle’s dynamic proxy generates are a lot more useful than LinFu.

Screenshot - LinFuGraph.png

Anyway I’m using LinFu at the moment as the proxy generator for Ninject. I will walk you through a sample application I built that will deal with the following subjects of Ninject, Lightspeed and NLog. For Ninject we will use the dependency injection and it’s interceptor possibilities to implement AOP style logging. For Lightspeed we will create our own logger to plug into the context so that we can log what Lightspeed does too. And we want NLog to log through Lightspeed to our database so we’ll be creating a custom target for NLog as well.

But let’s start at the beginning doing DI with Ninject :) .

The most important thing to remember: MAKE YOUR METHODS VIRTUAL. Once again make your methods virtual otherwise Ninject has a hard time generating proxies for your classes.

Ninject is different from most other DI Containers in that it doesn’t have XML-configuration, its configuration is done through code (wouldn’t be hard to add an XML configuration for it tho but what’s the point). No XML ?? Suits me fine, everybody that ever worked with me will agree : Ivan no like XML editing.  Ninject takes a modular approach by using modules that you pass to a kernel. This is pretty nice that means that an assembly can have a couple of different sets of Modules and all the caller of that assembly needs to do is add the module with the appropriate configuration to their kernel.

Ninject supports DI on constructors, properties, methods and fields: http://dojo.ninject.org/wiki/display/NINJECT/Injection+Patterns.
It basically boils down to decorating the item you want to inject with the attribute [Inject]

Ninject allows you to do a lot of configuration through the use of attributes. But I think I’ll leave it at that for today and continue this tomorrow.
Let’s look at a concrete class from what we’ve seen so far. The class below is the Logger implementation to plug into the LightSpeedContext. We will finish this later on but for now this will be enough to summarize today’s post.

using Ninject.Core;
using Ninject.Core.Logging;

using ILightSpeedLogger = Mindscape.LightSpeed.Logging.ILogger;
using INinjectLogger = Ninject.Core.Logging.ILogger;

namespace LoggingDemo.UI.Integration
{
///
/// This class intercepts logging messages from the LightSpeed context and
/// sends them to our NLog logger.
///
public class LightSpeedLogger : ILightSpeedLogger
{
private readonly INinjectLogger logger = NullLogger.Instance;

public LightSpeedLogger()
{
}

[Inject]
public LightSpeedLogger(INinjectLogger logger)
{
this.logger = logger;
}

#region ILogger Members

public virtual void LogSql(object sql)
{
logger.Info(sql.ToString());
}

public virtual void LogDebug(object text)
{
logger.Debug(text.ToString());
}

#endregion
}
}

Let me know what you think :)

kick it on DotNetKicks.com


Recent Flickrs

    Blogroll

    Recent Listening

    Scrobbler