<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://devlicio.us/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Krzysztof Kozmic</title><link>http://devlicio.us/blogs/krzysztof_kozmic/default.aspx</link><description /><dc:language>en</dc:language><generator>CommunityServer 2008.5 SP1 (Build: 31106.3070)</generator><item><title>On Testing: Why write tests?</title><link>http://devlicio.us/blogs/krzysztof_kozmic/archive/2013/01/19/on-testing-why-write-tests.aspx</link><pubDate>Sat, 19 Jan 2013 08:19:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:71176</guid><dc:creator>Krzysztof Koźmic</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/krzysztof_kozmic/rsscomments.aspx?PostID=71176</wfw:commentRss><comments>http://devlicio.us/blogs/krzysztof_kozmic/archive/2013/01/19/on-testing-why-write-tests.aspx#comments</comments><description>&lt;blockquote&gt;
&lt;p&gt;This post is secod part of my &lt;a href="http://kozmic.net/2012/11/27/on-testing/"&gt;Back to basics: on testing&lt;/a&gt; series.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Developers writing tests&lt;/h3&gt;
&lt;p&gt;People new to software, or coming from organizations where all testing is done by dedicated people often find the idea of developers doing testing bizarre.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/testing.jpg"&gt;&lt;img src="http://devlicio.us/resized-image.ashx/__size/550x0/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/testing.jpg" border="0" alt="" /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;After all, we&amp;#39;re the highly trained, educated professionals. We get payed to do the hard bits. Clicking around the UI to see if a label is misaligned or an app crashed surely should be delegated to somebody else, outsourced even.&lt;/p&gt;
&lt;p&gt;Truth is, there are various kinds of tests, and while there is value in UI tasting (automated or not) we&amp;#39;ll concetrate at somethig else first.&lt;/p&gt;
&lt;h3&gt;You write the tests for your future self&lt;/h3&gt;
&lt;p&gt;The idea of developers writing tests came not from academia but from the field. From people who spent years developing successful software. And as you get out there, and start working with teams of people, on real life big systems that solve real problems, you realise that some things you belived (or in fact were taught) to be true, are not.&lt;/p&gt;
&lt;p&gt;We&amp;#39;ll get into the details as we progress with this series, but let&amp;#39;s start with the biggest one:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The code is written, and read, and read, and read and read some more and modified, and read, and modified again, and read some more again and then few months later read yet again and again&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;You may notice there&amp;#39;s much more reading than writing there. That is true for most code - you don&amp;#39;t just write and forget it, like is the case with coding assignments at unversity. Real-life code is long lived, often expanded and modified and commonly the person doing the expanding is not the person who originally wrote the code. In fact the original author may have already moved on to work elsewhere.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;How do you know what the code does?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;How do you know where to make the change?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;How do you know your change didn&amp;#39;t break any of the assumptions that code interacting with the bit you changed makse about it?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;How do you know the change you made works the way you wanted it to?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;How do you know the API you created (in other words the public methods) are easy to use and will make sense to the other developers using it (that may also be you few weeks from now!).&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;These&lt;/strong&gt; are the reasons for writing tests. Tests are the most economical way of ensuring the change you will make two months from now fit in the design constrants you designed today. Tests are the fastest way for other developers (or again, future you) to get a feel of how a piece of code works; what it does, and how you&amp;#39;re supposed to use it.&lt;/p&gt;
&lt;h3&gt;Don&amp;#39;t just take my word for it&lt;/h3&gt;
&lt;p&gt;In the next part of the series we&amp;#39;ll start looking at actual code, writing some tests, and explaining the concepts around them.&lt;/p&gt;
&lt;p&gt;Until then, if you have any questions, or suggestions as to what to cover in future posts of the series, feel free to leave a comment.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=71176" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/krzysztof_kozmic/archive/tags/testing/default.aspx">testing</category><category domain="http://devlicio.us/blogs/krzysztof_kozmic/archive/tags/back+to+basics/default.aspx">back to basics</category></item><item><title>On testing</title><link>http://devlicio.us/blogs/krzysztof_kozmic/archive/2012/11/27/on-testing.aspx</link><pubDate>Tue, 27 Nov 2012 06:43:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:70528</guid><dc:creator>Krzysztof Koźmic</dc:creator><slash:comments>5</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/krzysztof_kozmic/rsscomments.aspx?PostID=70528</wfw:commentRss><comments>http://devlicio.us/blogs/krzysztof_kozmic/archive/2012/11/27/on-testing.aspx#comments</comments><description>&lt;p&gt;Over the last few years I&amp;#39;ve been mostly blogging about various random topics. Most often those were related to Windsor, discussing its new and upcoming features, announcing releases, and taking in-depth look and its underpinning principles.&lt;/p&gt;
&lt;p&gt;Another bucket was one-off posts discussing various aspects of software development, mostly out of larger context and not really caring if you, dear reader, have the experience and understanding of the topic or not.&lt;/p&gt;
&lt;h3&gt;Back to basics&lt;/h3&gt;
&lt;p&gt;Recently I had an interesting discussion with several people on twitter about basics. More precisely about basics behind writing tests.&lt;/p&gt;
&lt;p&gt;It seems to me, and I&amp;#39;m guilty of that myself, that us, the developers, chasing the latest great thing forget about the basics. When was the last time you read a blogpost about the importance of testing? When was the last time you read about how to write tests, what to look out for, and how to keep the quality of your tests high and the maintenance cost low?&lt;/p&gt;
&lt;p&gt;Several years ago I got a lot of value myself by reading blogs that taught me what is important in software, and I wouldn&amp;#39;t be the developer I am today, if it wasn&amp;#39;t for those people, who dedicated their time to share their experience and knowledge.&lt;/p&gt;
&lt;p&gt;I may not be subscribing to the &lt;em&gt;right&lt;/em&gt; blogs anymore, but I noticed those posts are much less frequent these days. To help fill the void I decided to concentrate a bit more on the fundamentals in the future, starting with what will hopefully evolve into a series of blogposts about tests.&lt;/p&gt;
&lt;h3&gt;Feedback&lt;/h3&gt;
&lt;p&gt;Do you think it&amp;#39;s a good idea? Any particular topics you would like me to emphasise, and areas to explore? Let me know in the comments. First post will be coming soon(ish).&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=70528" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/krzysztof_kozmic/archive/tags/testing/default.aspx">testing</category></item><item><title>IoC container solves a problem you might not have but it's a nice problem to have</title><link>http://devlicio.us/blogs/krzysztof_kozmic/archive/2012/10/23/ioc-container-solves-a-problem-you-might-not-have-but-it-s-a-nice-problem-to-have.aspx</link><pubDate>Mon, 22 Oct 2012 22:03:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:70408</guid><dc:creator>Krzysztof Koźmic</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/krzysztof_kozmic/rsscomments.aspx?PostID=70408</wfw:commentRss><comments>http://devlicio.us/blogs/krzysztof_kozmic/archive/2012/10/23/ioc-container-solves-a-problem-you-might-not-have-but-it-s-a-nice-problem-to-have.aspx#comments</comments><description>&lt;h3&gt;On frameworks and libraries&lt;/h3&gt;
&lt;p&gt;
A logging framework helps you log what&amp;#39;s happening in your application. A UI framework helps you render and animate UIs to the user. A communication library helps connecting parts of a distributed system. All of these tasks and concepts are pretty easy to understand. They are quite down to earth, and therefore, at a high level at least, easy to explain. They produce &lt;em&gt;tangible&lt;/em&gt;, &lt;em&gt;additive&amp;nbsp;&lt;/em&gt;difference in your application. Also the code of your application changes in order to use those frameworks and libraries. You add a logging framework, you write some code against its API and you end up with a file on your disk, or some text in your console. You add a communication library, inherit some base classes, implement some interfaces to designate communication endpoints of your application and you can see two processes exchanging information. I hope you get the picture and I don&amp;#39;t need do go on describing the tangible, additive and visible results of using a UI framework.
&lt;/p&gt;
&lt;h3&gt;What about IoC container?&lt;/h3&gt;
&lt;p&gt;
So what about inversion of control containers? There&amp;#39;s a lot of confusion around what they do, and why you should use one at all. Every now and then I meet a developer, who says they read all the definitions, introductions and basic examples, and they still don&amp;#39;t get why would they use a container. Other times I&amp;#39;m having discussions that can be summarised as (slightly exaggerated for dramatic effect):
&lt;/p&gt;
&lt;blockquote&gt;I got one of the IoC containers, put it in my application, and then all hell broke loose. We got memory leaks, things weren&amp;#39;t appearing where they should, users were seing other users&amp;#39; data, we had to recycle the pool every hour because we were running out of database connections, and the app got very slow. Ah and also it destroyed maintainability of our code, because we never knew when something is safe to refactor, since we never knew where and who would try to get them from the container.&lt;/blockquote&gt;
&lt;p&gt;
Let&amp;#39;s ignore the details for now and concentrate on the wider sentiment.
&lt;/p&gt;
&lt;h3&gt;So? Should I use it or not?&lt;/h3&gt;
&lt;p&gt;
The sentiment is one of confusion,&amp;nbsp;scepticism&amp;nbsp;and frustration. Was it a good idea to use the container? Should we have not used it? Would &lt;em&gt;I&lt;/em&gt; use it if I was leading the team? Truth is, those aren&amp;#39;t necessarily the right questions to ask. You can&amp;#39;t answer them in a vacuum. Should I use my phone to twitter when I&amp;#39;m on the bus? While the answer might be &amp;quot;sure, why not&amp;quot; if you&amp;#39;re a passenger, it would be unequivocally &amp;quot;don&amp;#39;t even think about reaching for your phone&amp;quot; if you&amp;#39;re the driver. I have seen applications where &amp;nbsp;introducing a container immediately, would only worsen things. I also haven&amp;#39;t worked with any .NET application where, if architected the way &lt;em&gt;I&amp;nbsp;&lt;/em&gt;like to do things, the container wouldn&amp;#39;t be beneficial in the long term. It all boils down to the fact that container solves certain problems that arise if and when you build your applications a certain way, and unless you do, you&amp;#39;re not going to see the benefits it brings, simply because the problems container solves will not be the main problems you&amp;#39;ll be facing, or will not appear in your application at all.
&lt;/p&gt;
&lt;h3&gt;What sort of architecture are we talking about?&lt;/h3&gt;
&lt;p&gt;
Container has certain requirements&amp;nbsp;in order to work smoothly. &amp;nbsp;First and foremost it requires structure and order. At a mechanical level, container takes over certain level of control over low level, mundane details of your &amp;nbsp;application&amp;#39;s infrastructure. It is however still a tool, and unless the environment where it operates is clean, with well defined limited number of abstractions it will struggle, and so will you, trying to get it to work.&lt;/p&gt;
&lt;p&gt;There&amp;#39;s a lot of content in the sentence above so let&amp;#39;s dig a bit deeper.&lt;/p&gt;
&lt;p&gt;The assumption containers are making is, that you do have abstractions. Getting a little bit ahead of ourselves, one of the main reason for using the container is to maintain lose coupling in our code. The way we achieve this is by constructing our types in such a way that they do not depend directly on other concrete classes. Regardless if it&amp;#39;s a high level type, or low level type, instead of depending on one another directly, container expects they will depend on abstractions.&lt;/p&gt;
&lt;p&gt;Another, related (pre)assumption is you will &amp;nbsp;build your classes to expose abstractions. And not just in any way, but keep them small and crisp (structure and order, remember). To maintain loose coupling, the abstractions are expected to provide just a single small task, and most classes will provide just a single abstraction.&lt;/p&gt;
&lt;p&gt;It is not uncommon for a concrete class to provide more than one abstraction (for example to bridge two parts of the system) but in that case the container assumes you will separate these two responsibilities into two abstractions.&lt;/p&gt;
&lt;p&gt;Large number of abstractions in your system will be reusable, that is a single abstraction will be exposed by more than one type. In cases like that, the container assumes all the implementations will obey the contract of the abstraction, that is they will all behave in a way that will not be surprising to anyone consuming the abstraction without knowing what concrete implementation is behind it.
&lt;/p&gt;
&lt;p&gt;The point above is especially important to provide class level extensibility. Certain types in your system will depend on a collection of dependencies, and you should not have to go back and change them, whenever you add a new type ending up in that collection. The assumption is, the code using the abstractions, as well as the abstractions themselves are built in such a way, that the type can be extended by swapping (or adding new) dependencies it has, without the type itself having to change.
&lt;/p&gt;
&lt;h3&gt;That&amp;#39;s a lot of assumptions, isn&amp;#39;t it?&lt;/h3&gt;
&lt;p&gt;
You may say the container makes quite a number of assumptions (or requirements!) about how your application is structured. You wouldn&amp;#39;t be wrong.
&lt;/p&gt;
&lt;p&gt;However if you look up and read the previous section again, forgetting that we are talking about container, does this feel like an architecture you should be striving for anyway? Does it feel like good, maintainable object oriented architecture? If it does, then that&amp;#39;s good, because that&amp;#39;s intentional.
&lt;/p&gt;
&lt;p&gt;A container doesn&amp;#39;t put any artificial or arbitrary cumbersome constraints onto how you should build your application. It doesn&amp;#39;t ask you to compromise any good practices aiming at maximising testability, maintainability and readability of your code and architecture. On the contrary, it&amp;nbsp;encourages&amp;nbsp;and rewards you for that.
&lt;/p&gt;
&lt;h3&gt;It&amp;#39;s the inversion!&lt;/h3&gt;
&lt;p&gt;
Finally we&amp;#39;re at a point where we can talk about some answers. The container makes a lot of assumptions about how your code is structured for two reasons.
&lt;/p&gt;
&lt;p&gt;That makes the container different from logging framework or communication framework. None of them cares about how your code is structured. As long as you implement correct interfaces or inherit correct base classes, and are able to call the right API they don&amp;#39;t care.
&lt;/p&gt;
&lt;p&gt;Inversion of control containers are&amp;nbsp;&lt;em&gt;fundamentally&lt;/em&gt; different. They do not require your code to implement or inherit anything and there&amp;#39;s no API to call (outside of single place called&amp;nbsp;&lt;em&gt;composition root&lt;/em&gt;). Just by looking at code of your application, you can&amp;#39;t tell if there is a container involved or not.
&lt;/p&gt;
&lt;p&gt;That&amp;#39;s the&amp;nbsp;&lt;em&gt;inversion of control&lt;/em&gt; working. This is what confuses so many people when they first start using containers. The difference is so fundamental from most other frameworks and libraries that it may be hard to comprehend and make the switch.&lt;/p&gt;
&lt;p&gt;
Inversion of control confuses people and makes it harder to see the value a container brings because the value is not tangible and it is not additive.
&lt;/p&gt;
&lt;p&gt;Contrast that with the examples from the first section. With logging framework you can point a finger at a piece of code and say &lt;em&gt;&amp;quot;There, here&amp;#39;s the logging framework doing its thing&amp;quot;&lt;/em&gt;. You can point a finger at your screen, entry in Windows event log, or a file on disk and say &lt;em&gt;&amp;quot;There, here&amp;#39;s the result of logging framework doing its thing&amp;quot;&lt;/em&gt;.
&lt;/p&gt;
&lt;p&gt;Inversion of control container is just &amp;quot;out there&amp;quot;. You can&amp;#39;t see the work that it&amp;#39;s doing by inspecting your code. That ephemeralness and intangibility is what confuses many new users and makes it harder for them to see the value the container brings to the table.
&lt;/p&gt;
&lt;p&gt;To make things even slightly more confusing for newcomers, when you&amp;#39;re &lt;em&gt;using&lt;/em&gt; a container you don&amp;#39;t end up writing code to&amp;nbsp;&lt;em&gt;use&lt;/em&gt; the container (again, expect for a little bit of code to wire it up). You end up writing&amp;nbsp;&lt;em&gt;less&lt;/em&gt; code as a result of using the container, not more, which again is harder to measure and appreciate than code you can clearly see as a result of using other kinds of frameworks.
&lt;/p&gt;
&lt;h3&gt;What isn&amp;#39;t there...&lt;/h3&gt;
&lt;p&gt;
The second reason why container makes all of these assumptions about your code is very simple. Unless your architecture follows these rules, you simply will not have the problems that the containers are built to solve. And even if you do, they will be far from being your main concern.
&lt;/p&gt;
&lt;p&gt;Building your application according to the assumptions that the container is built upon (I hope by now you figured out that they are just &lt;a title="SOLID principles of object oriented design" href="http://en.wikipedia.org/wiki/SOLID_(object-oriented_design)" target="_blank"&gt;SOLID principles&lt;/a&gt; of good object oriented C# code) your application will be composed of types exposing certain characteristics.
&lt;/p&gt;
&lt;p&gt;Following Single Responsibility Principle will lead you down the road of having plenty of small classes.
&lt;/p&gt;
&lt;p&gt;Open Close Principle will lead you down the way of encapsulating the core logic of each type in it, and then delegating all other work to its dependencies, causing most of those small classes to have multiple dependencies.
&lt;/p&gt;
&lt;p&gt;Interface Segregation Principle will cause you to abstract most of those big number of classes by exposing an interface or an abstract class, further multiplying the number of types in your application.
&lt;/p&gt;
&lt;p&gt;Liskov Substitution Principle will force you to clearly shape your abstractions so that they can be used in a uniform way.
&lt;/p&gt;
&lt;p&gt;Finally, if you follow Dependency Inversion Principle your types will not only expose abstractions themselves, but also depend on abstractions rather than concrete types.
&lt;/p&gt;
&lt;p&gt;Overall you will have a big number of small classes working with a number of abstractions. Each of those classes will be concentrated on its own job and largely ambivalent (and abstracted from) about who is using it, and details of who it is using.
&lt;/p&gt;
&lt;p&gt;This leaves you with a problem of putting together a group of those small types (let&amp;#39;s call them &lt;a href="http://kozmic.pl/2012/07/03/ioc-concepts-component/" target="_blank"&gt;Components&lt;/a&gt;) in order to support a full, real life, end to end scenario. Not only will you have to put them together, but also, maintain and manage them throughout the lifetime of your application.
&lt;/p&gt;
&lt;p&gt;Each component will be slightly different. For some of them you will want to have just a single instance, that is reused everywhere, for others, you&amp;#39;ll want to provide a new instance each time one is needed, or may be reuse instances within the scope of a web request, or any other arbitrary scope.
&lt;/p&gt;
&lt;p&gt;Some of them will have decommission logic, like Dispose method. Some of them will have ambient steps associated with their lifecycle, like &amp;quot;subscribe me to certain events in event aggregator when I&amp;#39;m created and them unsubscribe me when I&amp;#39;m about to be destroyed&amp;quot;.
&lt;/p&gt;
&lt;p&gt;Also thanks to the power of abstractions and guarantees put in place by following Liskov Substitution Principle you&amp;#39;ll want to compose some of the components using a further set of design patterns. You&amp;#39;ll want to create Decorators, Chains of Responsibility, Composites etc.
&lt;/p&gt;
&lt;p&gt;Not to mention the fact that in addition to depending on abstractions exposed by other components (let&amp;#39;s call them &lt;a href="http://kozmic.pl/2012/07/02/ioc-concepts-service/" target="_blank"&gt;Services&lt;/a&gt;) your components may also have some configuration, or other &amp;quot;primitive&amp;quot; dependencies (like connection strings).
&lt;/p&gt;
&lt;p&gt;I hope you can see that the complexity of it all can quickly grow immensely. If you want to maintain loose coupling between your components, you will have to write a lot of code to put them together and maintain all the aforementioned qualities. The code to do that can quickly grow as well, both in size and complexity.
&lt;/p&gt;
&lt;h3&gt;Container to save the day&lt;/h3&gt;
&lt;p&gt;
Inversion of control containers exist to replace that code. I know it took me a while to get here, and I did it in a very roundabout way, but there you have it - that&amp;#39;s what IoC containers do - they help you stay sane, and reduce friction of development when adhering to good Object Oriented Design principles in language like C#.
&lt;/p&gt;
&lt;p&gt;I know it&amp;#39;s not a sexy and concise definition, and some of you will probably need to re-read this post for it to &amp;quot;click&amp;quot;. Don&amp;#39;t worry. It didn&amp;#39;t click for me at first either. The value and goal of IoC container is abstract and intangible, and the nomenclature doesn&amp;#39;t help either.
&lt;/p&gt;
&lt;h3&gt;The i-word&lt;/h3&gt;
&lt;p&gt;
Some people feel that a lot of misconceptions and misunderstanding about containers comes from their very name - inversion of control container. If you just hear someone say those words, and leave it to your imagination, you&amp;#39;ll most likely see... blank. Nothing. It&amp;#39;s so abstract, that unless you know what it means, it&amp;#39;s pretty much meaningless.
&lt;/p&gt;
&lt;p&gt;To alleviate that some people started referring to containers as Dependency Injection container. At first this sounds like a better option. We pretty much understand what dependency in context of relation between two objects is. Injection is also something that you can have a lot associations with, software related or otherwise. Sounds simpler, more down-to-earth, doesn&amp;#39;t it?
&lt;/p&gt;
&lt;p&gt;It does &lt;em&gt;sound&lt;/em&gt; like a better option, but in my experience it ends being a medicine that&amp;#39;s worse than the disease. While it doesn&amp;#39;t leave you with blank stare, it projects a wrong image of what a container does. By using the word &lt;em&gt;injection&lt;/em&gt; it emphasises the process of constructing the graph of dependencies, ignoring everything else the container does, especially the fact that it manages the whole lifetime of the object, not just its construction. As a result of that, in my experience, people who think about containers in terms of DI end up misusing the container and facing problems that arise from that.
&lt;/p&gt;
&lt;p&gt;That&amp;#39;s why, even though I&amp;#39;m quite aware Inversion of Control Container is a poor name, that doesn&amp;#39;t help much in understanding those tools, at least it doesn&amp;#39;t end up causing people to misunderstand them.
&lt;/p&gt;
&lt;h3&gt;In closing&lt;/h3&gt;
&lt;p&gt;
So there you have it. I admire your persistence if you made it that far. I hope this post will help people undersand what a container does, and why putting it in an application that&amp;#39;s not architected for it, may end up causing more problems than benefits.
&lt;/p&gt;
&lt;p&gt;I hope it made it clearer what having a container in a well designed application brings to the table. In fact I only spoke about the most basic and general usages scenario that every container supports. Beyond that particular containers have additional, sometimes very powerful features that will add additional benefit to your development process.
&lt;/p&gt;
&lt;p&gt;So even if you feel you don&amp;#39;t have a need for a container right now, having the problems that the container is meant to solve is often a sign of a good, object oriented architecture, and those are good problems to have.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=70408" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/krzysztof_kozmic/archive/tags/Design/default.aspx">Design</category><category domain="http://devlicio.us/blogs/krzysztof_kozmic/archive/tags/IoC/default.aspx">IoC</category><category domain="http://devlicio.us/blogs/krzysztof_kozmic/archive/tags/architecture/default.aspx">architecture</category></item><item><title>To constructor or to property dependency?</title><link>http://devlicio.us/blogs/krzysztof_kozmic/archive/2012/09/05/to-constructor-or-to-property-dependency.aspx</link><pubDate>Wed, 05 Sep 2012 12:32:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:70305</guid><dc:creator>Krzysztof Koźmic</dc:creator><slash:comments>10</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/krzysztof_kozmic/rsscomments.aspx?PostID=70305</wfw:commentRss><comments>http://devlicio.us/blogs/krzysztof_kozmic/archive/2012/09/05/to-constructor-or-to-property-dependency.aspx#comments</comments><description>&lt;p&gt;Us, devel&amp;shy;op&amp;shy;ers, are a bit like that comic strip (&lt;a href="http://xkcd.com/1095/"&gt;from always great xkcd&lt;/a&gt;):&lt;/p&gt;
&lt;p&gt;&lt;img alt="Crazy Straws" src="http://imgs.xkcd.com/comics/crazy_straws.png" title="The new crowd is heavily shaped by this guy named Eric, who&amp;#39;s basically the Paris Hilton of the amateur plastic crazy straw design world." /&gt;&lt;/p&gt;
&lt;p&gt;We can end&amp;shy;lessly debate over tabs ver&amp;shy;sus spaces (don&amp;#39;t even get me started), whether to use optional semi&amp;shy;colon or not, and other seem&amp;shy;ingly irrel&amp;shy;e&amp;shy;vant top&amp;shy;ics. We can have heated, informed debates with a lot of merit, or (much more often) not very con&amp;shy;struc&amp;shy;tive exchanges of opinions.&lt;/p&gt;
&lt;p&gt;I men&amp;shy;tion that to explic&amp;shy;itly point out, while this post might be per&amp;shy;ceived as one of such dis&amp;shy;cus&amp;shy;sions, the goal of it is not to be a flame&amp;shy;war bait, but to share some experience.&lt;/p&gt;
&lt;p&gt;So hav&amp;shy;ing said that, let&amp;#39;s cut to the chase.&lt;/p&gt;
&lt;h3&gt;Depen&amp;shy;den&amp;shy;cies, mechan&amp;shy;ics and semantics&lt;/h3&gt;
&lt;p&gt;Writ&amp;shy;ing soft&amp;shy;ware in an object ori&amp;shy;ented lan&amp;shy;guage, like C#, fol&amp;shy;low&amp;shy;ing estab&amp;shy;lished prac&amp;shy;tices (&lt;span class="caps"&gt;SOLID&lt;/span&gt; etc) we tend to end up with many types, con&amp;shy;cen&amp;shy;trated on doing one thing, and del&amp;shy;e&amp;shy;gat&amp;shy;ing the rest to others.&lt;/p&gt;
&lt;p&gt;Let&amp;#39;s take an arti&amp;shy;fi&amp;shy;cial exam&amp;shy;ple of a class that is sup&amp;shy;posed to han&amp;shy;dle sce&amp;shy;nario where a user moved and we need to update their address.&lt;/p&gt;
&lt;pre class="brush: csharp; title: ; notranslate"&gt;public class UserService: IUserService
{
   // some other members

   public void UserMoved(UserMovedCommand command)
   {
      var user = session.Get&amp;lt;User&amp;gt;(command.UserId);

      logger.Info(&amp;quot;Updating address for user {0} from {1} to {2}&amp;quot;, user.Id, user.Address, command.Address);

      user.UpdateAddress(command.Address);

      bus.Publish(new UserAddressUpdated(user.Id, user.Address));
   }
}
&lt;/pre&gt;
&lt;p&gt;There are four lines of code in this method, and three dif&amp;shy;fer&amp;shy;ent depen&amp;shy;den&amp;shy;cies are in use: ses&amp;shy;sion, log&amp;shy;ger and bus. As an author of this code, you have a few options of sup&amp;shy;ply&amp;shy;ing those depen&amp;shy;den&amp;shy;cies, two of which that we&amp;#39;re going to con&amp;shy;cen&amp;shy;trate on (and by far the most pop&amp;shy;u&amp;shy;lar) are con&amp;shy;struc&amp;shy;tor depen&amp;shy;den&amp;shy;cies and prop&amp;shy;erty dependencies.&lt;/p&gt;
&lt;h3&gt;Tra&amp;shy;di&amp;shy;tional school of thought&lt;/h3&gt;
&lt;p&gt;Tra&amp;shy;di&amp;shy;tional approach to that prob&amp;shy;lem among C# devel&amp;shy;op&amp;shy;ers goes some&amp;shy;thing like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Use con&amp;shy;struc&amp;shy;tor for required depen&amp;shy;den&amp;shy;cies and prop&amp;shy;er&amp;shy;ties for optional dependencies.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This option is by far the most pop&amp;shy;u&amp;shy;lar and I used to fol&amp;shy;low it myself for a long time. Recently how&amp;shy;ever, at first uncon&amp;shy;sciously, I moved away from it.&lt;/p&gt;
&lt;p&gt;While in the&amp;shy;ory it&amp;#39;s a neat, arbi&amp;shy;trary rule that&amp;#39;s easy to fol&amp;shy;low, in prac&amp;shy;tice I found it is based on a flawed premise. The premise is this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;By look&amp;shy;ing at the class&amp;#39; con&amp;shy;struc&amp;shy;tor and prop&amp;shy;er&amp;shy;ties you will be able to eas&amp;shy;ily see the min&amp;shy;i&amp;shy;mal set of required depen&amp;shy;den&amp;shy;cies (those that go into the con&amp;shy;struc&amp;shy;tor) and optional set that can be sup&amp;shy;plied, but the class doesn&amp;#39;t require them (those are exposed as properties).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Fol&amp;shy;low&amp;shy;ing the rule we might build our class like that:&lt;/p&gt;
&lt;pre class="brush: csharp; title: ; notranslate"&gt;public class UserService: IUserService
{
   // some other members

   public UserService(ISession session, IBus bus)
   {
      //the obvious
   }

   public ILogger Logger {get; set;}
}
&lt;/pre&gt;
&lt;p&gt;This assumes that ses&amp;shy;sion and bus are required and log&amp;shy;ger is not (usu&amp;shy;ally it would be ini&amp;shy;tialised to some sort of NullLogger).&lt;/p&gt;
&lt;p&gt;In prac&amp;shy;tice I noticed a few things that make use&amp;shy;ful&amp;shy;ness of this rule questionable:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It ignores con&amp;shy;struc&amp;shy;tor over&amp;shy;loads. If I have another con&amp;shy;struc&amp;shy;tor that takes just ses&amp;shy;sion does it mean bus is an optional or manda&amp;shy;tory depen&amp;shy;dency? Even with&amp;shy;out over&amp;shy;load&amp;shy;ing, in C# 4 or later, I can default my con&amp;shy;struc&amp;shy;tor para&amp;shy;me&amp;shy;ters to null. Does it make them required or mandatory?&lt;/li&gt;
&lt;li&gt;It ignores the fact that in real&amp;shy;ity I very rarely, if ever, have really optional depen&amp;shy;den&amp;shy;cies. Notice the first code sam&amp;shy;ple assumes all of its depen&amp;shy;den&amp;shy;cies, includ&amp;shy;ing log&amp;shy;ger, are not null. If it was truly optional, I should prob&amp;shy;a&amp;shy;bly pro&amp;shy;tect myself from Null&amp;shy;Ref&amp;shy;er&amp;shy;ence&amp;shy;Ex&amp;shy;cep&amp;shy;tions, and in the process com&amp;shy;pletely destroy read&amp;shy;abil&amp;shy;ity of the method, allow&amp;shy;ing it to grow in size for no real benefit.&lt;/li&gt;
&lt;li&gt;It ignores the fact that I will almost never con&amp;shy;struct instances of those classes myself, del&amp;shy;e&amp;shy;gat&amp;shy;ing this task to my IoC con&amp;shy;tainer. Most mature IoC con&amp;shy;tain&amp;shy;ers are able to han&amp;shy;dle con&amp;shy;struc&amp;shy;tor over&amp;shy;loads and defaulted con&amp;shy;struc&amp;shy;tor para&amp;shy;me&amp;shy;ters, as well as mak&amp;shy;ing prop&amp;shy;er&amp;shy;ties required, ren&amp;shy;der&amp;shy;ing the argu&amp;shy;ment about required ver&amp;shy;sus optional moot.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Another, more prac&amp;shy;ti&amp;shy;cal rule, is this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Use con&amp;shy;struc&amp;shy;tor for not-changing depen&amp;shy;den&amp;shy;cies and prop&amp;shy;er&amp;shy;ties for ones that can change dur&amp;shy;ing object&amp;#39;s lifetime.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In other words, ses&amp;shy;sion and bus would end up being pri&amp;shy;vate read&amp;shy;only fields &amp;mdash; the C# com&amp;shy;piler would enforce that once we set them (option&amp;shy;ally val&amp;shy;i&amp;shy;dat&amp;shy;ing them first) the fields in the con&amp;shy;struc&amp;shy;tor, we are guar&amp;shy;an&amp;shy;teed to be deal&amp;shy;ing with the same (cor&amp;shy;rect, not null) objects ever after. On the other hand, Log&amp;shy;ger is up in the air, since tech&amp;shy;ni&amp;shy;cally at any point in time some&amp;shy;one can swap it for a dif&amp;shy;fer&amp;shy;ent instance, or set it to null. There&amp;shy;fore, what usu&amp;shy;ally log&amp;shy;i&amp;shy;cally fol&amp;shy;lows from there, is that prop&amp;shy;erty depen&amp;shy;den&amp;shy;cies should be avoided and every&amp;shy;thing should go through the constructor.&lt;/p&gt;
&lt;p&gt;I used to be the fol&amp;shy;lower of this rule until quite recently, but then it does have its flaws as well.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It leads to some nasty code in sub&amp;shy;classes where the base class has depen&amp;shy;den&amp;shy;cies. One exam&amp;shy;ple I saw recently was a &lt;span class="caps"&gt;WPF&lt;/span&gt; view model base class with depen&amp;shy;dency on dis&amp;shy;patcher. Because of that every sin&amp;shy;gle (and there were many) view model inher&amp;shy;it&amp;shy;ing from it, needed to have a con&amp;shy;struc&amp;shy;tor declared that takes dis&amp;shy;patcher and passes it up to the base con&amp;shy;struc&amp;shy;tor. Now imag&amp;shy;ine what hap&amp;shy;pens when you find you need event aggre&amp;shy;ga&amp;shy;tor in every view model. You will need to alter every sin&amp;shy;gle view model class you have to add that, and that&amp;#39;s a refac&amp;shy;tor&amp;shy;ing ReSharper will not aid you with.&lt;/li&gt;
&lt;li&gt;It trusts the com&amp;shy;piler more than devel&amp;shy;op&amp;shy;ers. Just because a set&amp;shy;ter is pub&amp;shy;lic, doesn&amp;#39;t mean the devel&amp;shy;op&amp;shy;ers will write code set&amp;shy;ting it to some ran&amp;shy;dom val&amp;shy;ues all over the place. It is all a mat&amp;shy;ter of con&amp;shy;ven&amp;shy;tions used in your par&amp;shy;tic&amp;shy;u&amp;shy;lar team. On the team I&amp;#39;m cur&amp;shy;rently work&amp;shy;ing with the rule that every&amp;shy;body knows and fol&amp;shy;lows is we do not use prop&amp;shy;er&amp;shy;ties, even set&amp;shy;table ones, to reas&amp;shy;sign depen&amp;shy;den&amp;shy;cies, we&amp;#39;re using meth&amp;shy;ods for that. There&amp;shy;fore, based on the assump&amp;shy;tion that devel&amp;shy;op&amp;shy;ers can be trusted, when read&amp;shy;ing the code and see&amp;shy;ing a prop&amp;shy;erty I know it won&amp;#39;t be used to change state, so read&amp;shy;abil&amp;shy;ity and imme&amp;shy;di&amp;shy;ate under&amp;shy;stand&amp;shy;ing of the code does not suffer.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In real&amp;shy;ity, I don&amp;#39;t actu&amp;shy;ally think the cur&amp;shy;rent one, or few of my last projects had even a require&amp;shy;ment to swap ser&amp;shy;vice depen&amp;shy;den&amp;shy;cies. Gen&amp;shy;er&amp;shy;ally you will direct your depen&amp;shy;dency graphs from more to less volatile objects (that is object will depend on objects with equal or longer lifes&amp;shy;pan). In few cases where that&amp;#39;s not the case the depen&amp;shy;den&amp;shy;cies would be pulled from a fac&amp;shy;tory, and used only within the scope of a sin&amp;shy;gle method, there&amp;shy;fore not being avail&amp;shy;able to the out&amp;shy;side world. The only sce&amp;shy;nario where a long-lived depen&amp;shy;dency would be swapped that I can think of, is some sort of failover or circuit-breaker, but then again, that would be likely dealt with inter&amp;shy;nally, inside the component.&lt;/p&gt;
&lt;p&gt;So, look&amp;shy;ing back at the code I tend to write, all depen&amp;shy;den&amp;shy;cies tend to be manda&amp;shy;tory, and all of them tend to not change after the object has been created.&lt;/p&gt;
&lt;h3&gt;What then?&lt;/h3&gt;
&lt;p&gt;This robs the afore&amp;shy;men&amp;shy;tioned approaches from their adver&amp;shy;tised ben&amp;shy;e&amp;shy;fits. As such I tend to draw the divi&amp;shy;sion along dif&amp;shy;fer&amp;shy;ent lines. It does work for me quite well so far, and in my mind, offers a few ben&amp;shy;e&amp;shy;fits. The rule I fol&amp;shy;low these days can be explained as follows:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Use con&amp;shy;struc&amp;shy;tor for application-level depen&amp;shy;den&amp;shy;cies and prop&amp;shy;er&amp;shy;ties for infra&amp;shy;struc&amp;shy;ture or inte&amp;shy;gra&amp;shy;tion dependencies.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;In other words, the depen&amp;shy;den&amp;shy;cies that are part of the essence of what the type is doing go into the con&amp;shy;struc&amp;shy;tor, and depen&amp;shy;den&amp;shy;cies that are part of the &amp;quot;back&amp;shy;ground&amp;quot; go via properties.&lt;/p&gt;
&lt;p&gt;Using our exam&amp;shy;ple from before, with this approach the ses&amp;shy;sion would come via con&amp;shy;struc&amp;shy;tor. It is part of the essence of what the class is doing, being used to obtain the very user whose address infor&amp;shy;ma&amp;shy;tion we want to update. Log&amp;shy;ging and pub&amp;shy;lish&amp;shy;ing the infor&amp;shy;ma&amp;shy;tion onto the bus are some&amp;shy;what less essen&amp;shy;tial to the task, being more of an infra&amp;shy;struc&amp;shy;ture con&amp;shy;cerns, there&amp;shy;fore bus and log&amp;shy;ger would be exposed as properties.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;This approach clearly puts dis&amp;shy;tinc&amp;shy;tion between what&amp;#39;s essen&amp;shy;tial, busi&amp;shy;ness logic, and what is book&amp;shy;keep&amp;shy;ing. Prop&amp;shy;er&amp;shy;ties and fields have dif&amp;shy;fer&amp;shy;ent nam&amp;shy;ing con&amp;shy;ven&amp;shy;tions, and (espe&amp;shy;cially with ReSharper&amp;#39;s &amp;#39;Color iden&amp;shy;ti&amp;shy;fiers&amp;#39; option) with my code colour&amp;shy;ing scheme have sig&amp;shy;nif&amp;shy;i&amp;shy;cantly dif&amp;shy;fer&amp;shy;ent colours. This makes is much eas&amp;shy;ier to find what really is impor&amp;shy;tant in code.&lt;/li&gt;
&lt;li&gt;Given the infra&amp;shy;struc&amp;shy;ture level depen&amp;shy;den&amp;shy;cies tend to be pushed up to base classes (like in the View&amp;shy;Model exam&amp;shy;ple with Dis&amp;shy;patcher and Even&amp;shy;tAg&amp;shy;gre&amp;shy;ga&amp;shy;tor) the inher&amp;shy;i&amp;shy;tors end up being leaner and more readable.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;In clos&amp;shy;ing&lt;/h3&gt;
&lt;p&gt;So there you have it. It may be less pure, but trades purity for read&amp;shy;abil&amp;shy;ity and reduces amount of boil&amp;shy;er&amp;shy;plate code, and that&amp;#39;s a trade&amp;shy;off I am happy to make.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=70305" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/krzysztof_kozmic/archive/tags/Design/default.aspx">Design</category><category domain="http://devlicio.us/blogs/krzysztof_kozmic/archive/tags/c_2300_/default.aspx">c#</category></item><item><title>Using ConventionTests</title><link>http://devlicio.us/blogs/krzysztof_kozmic/archive/2012/06/14/using-conventiontests.aspx</link><pubDate>Thu, 14 Jun 2012 08:19:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:69979</guid><dc:creator>Krzysztof Koźmic</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/krzysztof_kozmic/rsscomments.aspx?PostID=69979</wfw:commentRss><comments>http://devlicio.us/blogs/krzysztof_kozmic/archive/2012/06/14/using-conventiontests.aspx#comments</comments><description>&lt;h3&gt;About conventions&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;m a big fan of using conventions when developing applications. I blogged about it in the past (&lt;a href="http://kozmic.pl/2010/03/21/validate-your-conventions/" target="_blank"&gt;here&lt;/a&gt;, &lt;a href="http://kozmic.pl/2010/04/08/build-your-conventions/" target="_blank"&gt;here&lt;/a&gt; and later &lt;a href="http://kozmic.pl/2011/03/09/testing-conventions/" target="_blank"&gt;here&lt;/a&gt;). I also gave a talk about my experience with this approach and how I currently use it at &lt;a href="http://ndcoslo.com/" target="_blank"&gt;NDC&lt;/a&gt; last week (slides are available &lt;a href="http://kozmic.pl/presentations/" target="_blank"&gt;here&lt;/a&gt;, video should be posted in a few weeks).&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;One problem I faced when trying to build convention validation tests was lack of simple API that would allow me to build the validation rules for my tests. I built a spike of such library (called &lt;a href="https://github.com/kkozmic/Norman" target="_blank"&gt;Norman&lt;/a&gt;) last year. It was meant to be full-featured generic convention-validation engine, built on top of &lt;a href="http://devlicio.us/controlpanel/blogs/posteditor.aspx/www.mono-project.com/Cecil" target="_blank"&gt;Mono.Cecil&lt;/a&gt; that would be able to validate rules inside method bodies (think rules like &amp;ldquo;no ViewModel can call data access code&amp;rdquo;). I quickly abandoned it, not being able to come up with simple and concise API that at the same time would be generic enough to cover every possible scenario.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;About ConventionTests&lt;/h3&gt;
&lt;p&gt;Having failed with Norman&amp;rsquo;s approach on a later project I approached the problem from a completely different angle. This is based on observation regarding conventions I tend to use &amp;ndash; they, in majority of cases, tend to be based on information about types, and internal models of frameworks I tend to use. In other words &amp;ndash; information that can be easily obtained via plain Reflection.&lt;/p&gt;
&lt;p&gt;Also limiting myself to very few scenarios allowed me to come up with a focused, simple and concise API. That&amp;rsquo;s how &lt;a href="http://nuget.org/packages/ConventionTests" target="_blank"&gt;ConventionTests&lt;/a&gt; project was born.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;Using ConventionTests&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://nuget.org/packages/ConventionTests" target="_blank"&gt;ConventionTests&lt;/a&gt; is a simple code-only Nuget that provides very minimalistic and limited API enforcing certain structure when writing convention tests and integrating with NUnit (more on that below). Installing it will add two .cs files to the project and a few dependencies (NUnit, Windsor and ApprovalTests).&lt;/p&gt;
&lt;p&gt;&lt;a href="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/image_5F00_2.png"&gt;&lt;img style="border-right-width:0px;margin:5px 0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="image" alt="image" src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/image_5F00_thumb.png" width="359" border="0" height="235" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;ConventionTests.NUnit file is where all the relevant code is located and __Run file is the file that runs your tests (why that is, later).&lt;/p&gt;
&lt;p&gt;The approach is to create a file per convention and name them in a descriptive manner, so that you can learn what the conventions you have in the project by just looking at the files in your Conventions folder, without having to open them.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Each convention test inherits (directly or indirectly from IConventionTest) interface. There&amp;rsquo;s an abstract implementation of the interface, ConventionTestBase and a few specialized implementations for common scenarios provided out of the box: Type-based one (ConventionTest) and two for Windsor (WindsorConventionTest, non-generic and generic for diagnostics-based tests).&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;Type-based convention tests&lt;/h3&gt;
&lt;p&gt;The most common and most generic group of conventions are ones based around types and type information. Conventions like &amp;ldquo;every controller&amp;rsquo;s name ends with &amp;lsquo;Controller&amp;rsquo;&amp;rdquo;, or &amp;ldquo;Every method on WCF service contracts must have OperationContractAttribute&amp;rdquo; are examples of such conventions.&lt;/p&gt;
&lt;p&gt;You write them by creating a class inheriting ConventionTest, which forces you to override one method. Here&amp;rsquo;s a minimal example:&lt;/p&gt;
&lt;div style="text-align:left;padding:4px;line-height:12pt;background-color:#f4f4f4;margin:20px 0px 10px;width:97.5%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;max-height:700px;font-size:8pt;overflow:auto;cursor:text;border:1px solid silver;" id="codeSnippetWrapper"&gt;
&lt;div style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;" id="codeSnippet"&gt;
&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; Controllers_have_Controller_suffix_in_type_name : ConventionTest&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;{&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;    &lt;span style="color:#0000ff;"&gt;protected&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;override&lt;/span&gt; ConventionData SetUp()&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;    {&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;        &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; ConventionData&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;            {&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;                Types = t =&amp;gt; t.IsConcrete&amp;lt;IController&amp;gt;(),&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;                Must = t =&amp;gt; t.Name.EndsWith(&lt;span style="color:#006080;"&gt;&amp;quot;Controller&amp;quot;&lt;/span&gt;)&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;            };&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;    }&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Hopefully the code is self-explanatory (it was designed to be). You specify two predicates. One to find types that your convention is concerning, and the other specifying what your convention demands. If you now run tests in your project (or in __Run.cs file) You will see the result similar to this:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/image_5F00_4.png"&gt;&lt;img style="border-right-width:0px;margin:5px 0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="image" alt="image" src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/image_5F00_thumb_5F00_1.png" width="482" border="0" height="241" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;In this case I had a single class implementing IController, named Foo, which obviously doesn&amp;rsquo;t follow the convention that&amp;rsquo;s why the test failed, giving me generic failure message which just lists the types that failed the test.&lt;/p&gt;
&lt;p&gt;To make it more readable I may want to make the test failure message more descriptive and actionable so that whoever sees a failing test like this will be able to know why their code is wrong and how to fix it.&lt;/p&gt;
&lt;div style="text-align:left;padding:4px;line-height:12pt;background-color:#f4f4f4;margin:20px 0px 10px;width:97.5%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;max-height:700px;font-size:8pt;overflow:auto;cursor:text;border:1px solid silver;" id="codeSnippetWrapper"&gt;
&lt;div style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;" id="codeSnippet"&gt;
&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;&lt;span style="color:#0000ff;"&gt;protected&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;override&lt;/span&gt; ConventionData SetUp()&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;{&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;    &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; ConventionData&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;        {&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;            Types = t =&amp;gt; t.IsConcrete&amp;lt;IController&amp;gt;(),&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;            Must = t =&amp;gt; t.Name.EndsWith(&lt;span style="color:#006080;"&gt;&amp;quot;Controller&amp;quot;&lt;/span&gt;),&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;            FailDescription = &lt;span style="color:#006080;"&gt;&amp;quot;Routing will not work unless controllers are named {something}Controller&amp;quot;&lt;/span&gt;,&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;            FailItemDescription = t =&amp;gt; t.ToString() + &lt;span style="color:#006080;"&gt;&amp;quot;. Name should be &amp;quot;&lt;/span&gt; + t.Name + &lt;span style="color:#006080;"&gt;&amp;quot;Controller perhaps?&amp;quot;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;        };&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;The two additional properties will cause the failure to look like this:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/image_5F00_6.png"&gt;&lt;img style="border-right-width:0px;margin:5px 0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="image" alt="image" src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/image_5F00_thumb_5F00_2.png" width="573" border="0" height="246" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;This tells the developer who sees that test not only were the problem is, but also why it is a problem, and suggests a solution.&lt;/p&gt;
&lt;p&gt;For scenarios where the convention is not all black and white and there are some legitimate exceptions to the rule there is built in integration with ApprovalTests framework (I blogged about ApprovalTests &lt;a href="http://kozmic.pl/2012/01/16/approval-testing-value-for-the-money/" target="_blank"&gt;here&lt;/a&gt;). I know that the convention I used here as an example is pretty black and white but assuming it wasn&amp;rsquo;t changing the code to:&lt;/p&gt;
&lt;div style="text-align:left;padding:4px;line-height:12pt;background-color:#f4f4f4;margin:20px 0px 10px;width:97.5%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;max-height:700px;font-size:8pt;overflow:auto;cursor:text;border:1px solid silver;" id="codeSnippetWrapper"&gt;
&lt;div style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;" id="codeSnippet"&gt;
&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;&lt;span style="color:#0000ff;"&gt;protected&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;override&lt;/span&gt; ConventionData SetUp()&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;{&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;    &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; ConventionData&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;        {&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;            Types = t =&amp;gt; t.IsConcrete&amp;lt;IController&amp;gt;(),&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;            Must = t =&amp;gt; t.Name.EndsWith(&lt;span style="color:#006080;"&gt;&amp;quot;Controller&amp;quot;&lt;/span&gt;),&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;            FailDescription = &lt;span style="color:#006080;"&gt;&amp;quot;Routing will not work unless controllers are named {something}Controller&amp;quot;&lt;/span&gt;,&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;            FailItemDescription = t =&amp;gt; t.ToString() + &lt;span style="color:#006080;"&gt;&amp;quot;. Name should be &amp;quot;&lt;/span&gt; + t.Name + &lt;span style="color:#006080;"&gt;&amp;quot;Controller perhaps?&amp;quot;&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;        }.WithApprovedExceptions(&lt;span style="color:#006080;"&gt;&amp;quot;Let&amp;#39;s say Foo has special routing or something&amp;quot;&lt;/span&gt;);&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;will change it to approval test where approved file will contain the output of the test, so in this case:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/image_5F00_8.png"&gt;&lt;img style="border-right-width:0px;margin:5px 0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="image" alt="image" src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/image_5F00_thumb_5F00_3.png" width="536" border="0" height="60" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;h3&gt;Windsor-based convention tests&lt;/h3&gt;
&lt;p&gt;Another common set of convention tests I tend to write are tests regarding my IoC container (and I tend to use &lt;a href="http://docs.castleproject.org/Windsor.MainPage.ashx" target="_blank"&gt;Castle Windsor&lt;/a&gt;, therefore that&amp;rsquo;s the one supported out of the box). The structure of the tests and API is similar, with difference being instead of types we&amp;rsquo;re dealing with Windsor&amp;rsquo;s component &lt;a href="http://docs.castleproject.org/Windsor.Handlers.ashx" target="_blank"&gt;Handlers&lt;/a&gt;.&lt;/p&gt;
&lt;div style="text-align:left;padding:4px;line-height:12pt;background-color:#f4f4f4;margin:20px 0px 10px;width:97.5%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;max-height:700px;font-size:8pt;overflow:auto;cursor:text;border:1px solid silver;" id="codeSnippetWrapper"&gt;
&lt;div style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;" id="codeSnippet"&gt;
&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; List_classes_registered_in_Windsor : WindsorConventionTest&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;{&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;    &lt;span style="color:#0000ff;"&gt;protected&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;override&lt;/span&gt; WindsorConventionData SetUp()&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;    {&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;        &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; WindsorConventionData(&lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; WindsorContainer()&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;                                                .Install(FromAssembly.Containing&amp;lt;AuditedAction&amp;gt;()))&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;            {&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;                FailDescription = &lt;span style="color:#006080;"&gt;&amp;quot;All Windsor components&amp;quot;&lt;/span&gt;,&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;                FailItemDescription = h =&amp;gt; BuildDetailedHandlerDescription(h)+&lt;span style="color:#006080;"&gt;&amp;quot; | &amp;quot;&lt;/span&gt;+&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;                    h.ComponentModel.GetLifestyleDescription(),&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;            }.WithApprovedExceptions(&lt;span style="color:#006080;"&gt;&amp;quot;We just list all of them.&amp;quot;&lt;/span&gt;);&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;&amp;nbsp;&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;    }&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;In this case we&amp;rsquo;re dealing with slightly different types but we follow the same pattern. We initialize the container and then specify predicates (if necessary) on its handlers. We don&amp;rsquo;t need to do that in which case all handlers from the container will be considered. This is useful to create (approval) test like this one that just lists all the components in the container, along with the list of services they expose and their lifestyle. With that you get quick insight into what&amp;rsquo;s in your container by just looking at the approved file. Moreover every change to the list of components will cause the test to fail, drawing your attention, to hopefully validate that the changes happening are indeed what you were expecting.&lt;/p&gt;
&lt;h3&gt;Windsor diagnostics-based convention tests&lt;/h3&gt;
&lt;p&gt;Windsor as some &lt;a href="http://docs.castleproject.org/Windsor.Debugger-views.ashx" target="_blank"&gt;built in diagnostics&lt;/a&gt; and there&amp;rsquo;s a base class for tests that take advantage of that. For example the following test will list all potentially misconfigured components.&lt;/p&gt;
&lt;div style="text-align:left;padding:4px;line-height:12pt;background-color:#f4f4f4;margin:20px 0px 10px;width:97.5%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;max-height:700px;font-size:8pt;overflow:auto;cursor:text;border:1px solid silver;" id="codeSnippetWrapper"&gt;
&lt;div style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;" id="codeSnippet"&gt;
&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; List_misconfigured_components_in_Windsor : &lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;    WindsorConventionTest&amp;lt;IPotentiallyMisconfiguredComponentsDiagnostic&amp;gt;&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;{&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;    &lt;span style="color:#0000ff;"&gt;protected&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;override&lt;/span&gt; WindsorConventionData&amp;lt;IHandler&amp;gt; SetUp()&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;    {&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;        &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;            &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; WindsorConventionData&amp;lt;IHandler&amp;gt;(&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;                &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; WindsorContainer().Install(FromAssembly.Containing&amp;lt;AuditedAction&amp;gt;()))&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;                {&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;                    FailDescription = &lt;span style="color:#006080;"&gt;&amp;quot;The following components come up as potentially unresolvable&amp;quot;&lt;/span&gt;,&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;                    FailItemDescription = MisconfiguredComponentDescription&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;                }.WithApprovedExceptions(&lt;span style="color:#006080;"&gt;&amp;quot;it&amp;#39;s *potentially* for a reason&amp;quot;&lt;/span&gt;);&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;    }&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;In this case instead of inspecting all handlers we go through handlers returned by the diagnostic (there&amp;rsquo;s another base class, with two generic parameters for diagnostics that do not deal with handlers). We make it an approval test so we can have an approved list of false-positives.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Those are the basic scenarios provided out of the box, however you can extend it to easily support more custom scenarios. For example, one case that happened on my current project just this week, was this. We&amp;rsquo;re using &lt;a href="http://nhforge.org" target="_blank"&gt;NHibernate&lt;/a&gt; and FluentNHibernate (by convention) and the default cascading on collections is set to &amp;ldquo;cascade all delete orphans&amp;rdquo;. This is not always the valid choice and for those cases we use mapping overrides.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;Custom convention tests&lt;/h3&gt;
&lt;p&gt;We wanted to create a convention test (with approval) that lists all our collections where we do cascade deletes, so that when we add a new collection the test would fail reminding us of the issue, and forcing us to pay attention to how we structure relationships in the application. To do this we could create a base NHibernateConventionTest and NHiibernateConventionData to create similar structure, or just build a simple one-class convention like that:&lt;/p&gt;
&lt;div style="text-align:left;padding:4px;line-height:12pt;background-color:#f4f4f4;margin:20px 0px 10px;width:97.5%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;max-height:700px;font-size:8pt;overflow:auto;cursor:text;border:1px solid silver;" id="codeSnippetWrapper"&gt;
&lt;div style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;" id="codeSnippet"&gt;
&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; List_collection_that_cascade_deletes:ConventionTestBase&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;{&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;    &lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;override&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; Execute()&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;    {&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;        &lt;span style="color:#008000;"&gt;// NH Bootstrapper is our custom class to set up NH&lt;/span&gt;&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;        var bootstrapper = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; NHibernateBootstrapper();&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;        var configuration = bootstrapper.BuildConfiguration();&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;&amp;nbsp;&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;        var message = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; StringBuilder(&lt;span style="color:#006080;"&gt;&amp;quot;Collections with cascade delete orphan&amp;quot;&lt;/span&gt;);&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;        &lt;span style="color:#0000ff;"&gt;foreach&lt;/span&gt; (var @&lt;span style="color:#0000ff;"&gt;class&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;in&lt;/span&gt; configuration.ClassMappings)&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;        {&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;            &lt;span style="color:#0000ff;"&gt;foreach&lt;/span&gt; (var property &lt;span style="color:#0000ff;"&gt;in&lt;/span&gt; @&lt;span style="color:#0000ff;"&gt;class&lt;/span&gt;.PropertyIterator)&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;            {&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;                &lt;span style="color:#0000ff;"&gt;if&lt;/span&gt;(property.CascadeStyle.HasOrphanDelete)&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;                {&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;                    message.AppendLine(@&lt;span style="color:#0000ff;"&gt;class&lt;/span&gt;.NodeName + &lt;span style="color:#006080;"&gt;&amp;quot;.&amp;quot;&lt;/span&gt; + property.Name);&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;                }&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;            }&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;        }&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;        Approve(message.ToString());&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;    }&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;This is obviously much more imperative and much less readable than the other tests, therefore I suggest in most casese you make the effort and try to make the tests as terse, readable and declarative as possible so that they truly read like a good executable documentation.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;And if you&amp;rsquo;re not sure how something works, remember the whole thing is a code-only nuget so you can just read the code.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://nuget.org/packages/ConventionTests" target="_blank"&gt;Get it here&lt;/a&gt;.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=69979" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/krzysztof_kozmic/archive/tags/.NET/default.aspx">.NET</category><category domain="http://devlicio.us/blogs/krzysztof_kozmic/archive/tags/Design/default.aspx">Design</category></item><item><title>How to force Nuget not to update log4net to 1.2.11</title><link>http://devlicio.us/blogs/krzysztof_kozmic/archive/2012/01/31/how-to-force-nuget-not-to-update-log4net-to-1-2-11.aspx</link><pubDate>Tue, 31 Jan 2012 12:28:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:69451</guid><dc:creator>Krzysztof Koźmic</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/krzysztof_kozmic/rsscomments.aspx?PostID=69451</wfw:commentRss><comments>http://devlicio.us/blogs/krzysztof_kozmic/archive/2012/01/31/how-to-force-nuget-not-to-update-log4net-to-1-2-11.aspx#comments</comments><description>&lt;p&gt;That&amp;rsquo;s a quick one. There&amp;rsquo;s been a new release of log4net recently that&amp;rsquo;s signed with a new key, and therefore is incompatible with old version 1.2.10.&lt;/p&gt;
&lt;p&gt;Therefore, due to near-ubiquity of the library in .NET space, it may cause some problems if you happen to have a dependency (direct or indirect) on it.&lt;/p&gt;
&lt;p&gt;The matters are made worse by Nuget&amp;rsquo;s default of getting the latest available version of the package. I dealt with this problem the other day, and I saw a few people in my twitter stream struggling with the same issue.&lt;/p&gt;
&lt;p&gt;The solution is quite simple. It&amp;rsquo;s not specific to log4net and I&amp;rsquo;m not picking on log4net here. Here&amp;rsquo;s how you can restrict Nuget&amp;rsquo;s package to specific version in your solution.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;So imagine you install a package that has a dependency on log4net. In this case, the dependency is specified as specifically version 1.2.10 (as opposed to Nuget&amp;rsquo;s default: this version of newer).&lt;/p&gt;
&lt;p&gt;&lt;a href="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/nuget_5F00_core_5F00_2.png"&gt;&lt;img style="border-bottom:0px;border-left:0px;display:inline;border-top:0px;border-right:0px;" title="nuget_core" alt="nuget_core" src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/nuget_5F00_core_5F00_thumb.png" border="0" height="287" width="660" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;If after that we install another package that also depends on log4net but doesn&amp;rsquo;t restrict the version, we&amp;rsquo;ll have a problem.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/nuget_5F00_log4net_5F00_fail_5F00_2.png"&gt;&lt;img style="border-bottom:0px;border-left:0px;display:inline;border-top:0px;border-right:0px;" title="nuget_log4net_fail" alt="nuget_log4net_fail" src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/nuget_5F00_log4net_5F00_fail_5F00_thumb.png" border="0" height="327" width="660" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;The package we were trying to install doesn&amp;rsquo;t get installed. Actually, even if it did, we would have a problem since it most likely was compiled against log4net 1.2.10 anyway, and if Nuget updated log4net to version 1.2.11 the app would throw an exception at runtime due to mismatched assembly.&lt;/p&gt;
&lt;p&gt;So there is a solution to restrict version of the package to specific version (in this case 1.2.10) &lt;a href="http://docs.nuget.org/docs/reference/versioning" target="_blank"&gt;as specified in the documentation.&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/nuget_5F00_log4net_5F00_fail_5F00_solution_5F00_2.png"&gt;&lt;img style="border-bottom:0px;border-left:0px;display:inline;border-top:0px;border-right:0px;" title="nuget_log4net_fail_solution" alt="nuget_log4net_fail_solution" src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/nuget_5F00_log4net_5F00_fail_5F00_solution_5F00_thumb.png" border="0" height="339" width="691" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;After adding allowedVersions=&amp;rdquo;[1.2.10]&amp;rdquo; we can try again and this time the package will install properly.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/nuget_5F00_log4net_5F00_fail_5F00_avoided_5F00_2.png"&gt;&lt;img style="border-bottom:0px;border-left:0px;display:inline;border-top:0px;border-right:0px;" title="nuget_log4net_fail_avoided" alt="nuget_log4net_fail_avoided" src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/nuget_5F00_log4net_5F00_fail_5F00_avoided_5F00_thumb.png" border="0" height="226" width="660" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;Notice it says it installed log4net 1.2.11. I checked my packages folder, and project dependencies and the version referenced was 1.2.10 so all is good.&lt;/p&gt;
&lt;p&gt;Hope that helps&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=69451" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/krzysztof_kozmic/archive/tags/.NET/default.aspx">.NET</category></item><item><title>Testing framework is not just for writing… tests</title><link>http://devlicio.us/blogs/krzysztof_kozmic/archive/2012/01/18/testing-framework-is-not-just-for-writing-tests.aspx</link><pubDate>Wed, 18 Jan 2012 13:06:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:69335</guid><dc:creator>Krzysztof Koźmic</dc:creator><slash:comments>9</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/krzysztof_kozmic/rsscomments.aspx?PostID=69335</wfw:commentRss><comments>http://devlicio.us/blogs/krzysztof_kozmic/archive/2012/01/18/testing-framework-is-not-just-for-writing-tests.aspx#comments</comments><description>&lt;p&gt;Quick question &amp;ndash; from the top of your head, without running the code, what is the result of:&lt;/p&gt;
&lt;div style="text-align:left;padding:4px;line-height:12pt;background-color:#f4f4f4;margin:20px 0px 10px;width:97.5%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;max-height:700px;font-size:8pt;overflow:auto;cursor:text;border:1px solid silver;" id="codeSnippetWrapper"&gt;
&lt;div style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;" id="codeSnippet"&gt;
&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;var foo = -00.053200000m; &lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;&amp;nbsp;&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;var result = foo.ToString(&lt;span style="color:#006080;"&gt;&amp;quot;##.##&amp;quot;&lt;/span&gt;);&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;Or a different one:&lt;/p&gt;
&lt;div style="text-align:left;padding:4px;line-height:12pt;background-color:#f4f4f4;margin:20px 0px 10px;width:97.5%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;max-height:700px;font-size:8pt;overflow:auto;cursor:text;border:1px solid silver;" id="codeSnippetWrapper"&gt;
&lt;div style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;" id="codeSnippet"&gt;
&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;var foo = &lt;span style="color:#006080;"&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;; &lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;var bar = &lt;span style="color:#006080;"&gt;&amp;quot;bar&amp;quot;&lt;/span&gt;; &lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;var foobar = &lt;span style="color:#006080;"&gt;&amp;quot;foo&amp;quot;&lt;/span&gt; + &lt;span style="color:#006080;"&gt;&amp;quot;bar&amp;quot;&lt;/span&gt;; &lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;var concaternated = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; StringBuilder(foo).Append(bar).ToString(); &lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;&amp;nbsp;&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;var result1 = AreEqual(foobar, concaternated); &lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;var result2 = Equals(foobar, concaternated);&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;&amp;nbsp;&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt; &lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;&amp;nbsp;&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;static&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;bool&lt;/span&gt; AreEqual(&lt;span style="color:#0000ff;"&gt;object&lt;/span&gt; one, &lt;span style="color:#0000ff;"&gt;object&lt;/span&gt; two) &lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;{ &lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;    &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; one == two; &lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;How about this one from NHibernate?&lt;/p&gt;
&lt;div style="text-align:left;padding:4px;line-height:12pt;background-color:#f4f4f4;margin:20px 0px 10px;width:97.5%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;max-height:700px;font-size:8pt;overflow:auto;cursor:text;border:1px solid silver;" id="codeSnippetWrapper"&gt;
&lt;div style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;" id="codeSnippet"&gt;
&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;var parent = session.Get&amp;lt;Parent&amp;gt;(1); &lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;&amp;nbsp;&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;DoSomething(parent.Child.Id); &lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;&amp;nbsp;&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;var result = NHibernateUtil.IsInitialized(parent.Child);&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h3&gt;The point being?&lt;/h3&gt;
&lt;p&gt;Well, if you can answer all of the above without running the code, &lt;a href="http://readify.net/work-with-us" target="_blank"&gt;we&amp;rsquo;re hiring&lt;/a&gt;. I don&amp;rsquo;t, and I suspect most people don&amp;rsquo;t either. That&amp;rsquo;s fine. Question is &amp;ndash; what are you going to do about it? What do you do when some 3rd party library, or part of standard library exhibits unexpected behaviour? How do you go about learning if what you think should happen, is really what does happen?&lt;/p&gt;
&lt;h3&gt;Scratchpad&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;ve seen people open up Visual Studio, create ConsoleApplication38, write some code using the API in question including plenty of Console.WriteLine along the way (curse whoever decided Client Profile should be the default for Console applications, switch to full .NET profile) compile, run and discard the code. And then repeat the process with ConsoleApplication39 next time.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The solution I&amp;rsquo;m using feels a bit more lightweight, and has worked for me well over the years. It is very simple &amp;ndash; I leverage my existing test framework and test runner. I create an empty test fixture called Scratchpad.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/scratchpad_5F00_2.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="scratchpad" alt="scratchpad" src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/scratchpad_5F00_thumb.png" border="0" height="185" width="198" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;&lt;a href="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/scratchpad_5F00_fixture_5F00_2.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="scratchpad_fixture" alt="scratchpad_fixture" src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/scratchpad_5F00_fixture_5F00_thumb.png" border="0" height="231" width="282" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;This class gets committed to the VCS repository. That way every member of the team gets their own scratchpad to play with and validate their theories, ideas and assumptions. However, as the name implies, this all is a one-off throwaway code. After all, you don&amp;rsquo;t really need to test the BCL. One would hope Microsoft already did a good job at that.&lt;/p&gt;
&lt;p&gt;If you&amp;rsquo;re using git, you can easily tell it not to track changes to the file, by running the following command (after you commit the file):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;git update-index --assume-unchanged Scratchpad.cs&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/scratchpad_5F00_git_5F00_2.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="scratchpad_git" alt="scratchpad_git" src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/scratchpad_5F00_git_5F00_thumb.png" border="0" height="210" width="636" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;With this simple set up you will have quick place to validate your assumptions (and answer questions about API behaviour) with little friction.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/scratchpad_5F00_test_5F00_4.png"&gt;&lt;img style="border-right-width:0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="scratchpad_test" alt="scratchpad_test" src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/scratchpad_5F00_test_5F00_thumb_5F00_1.png" border="0" height="147" width="383" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;So there you have it, a new, useful technique in your toolbelt.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=69335" width="1" height="1"&gt;</description></item><item><title>Approval testing – value for the money</title><link>http://devlicio.us/blogs/krzysztof_kozmic/archive/2012/01/16/approval-testing-value-for-the-money.aspx</link><pubDate>Mon, 16 Jan 2012 12:29:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:69327</guid><dc:creator>Krzysztof Koźmic</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/krzysztof_kozmic/rsscomments.aspx?PostID=69327</wfw:commentRss><comments>http://devlicio.us/blogs/krzysztof_kozmic/archive/2012/01/16/approval-testing-value-for-the-money.aspx#comments</comments><description>&lt;p&gt;I am a believer in the &lt;a href="http://kozmic.pl/2011/02/27/tests-are-your-airbag/" target="_blank"&gt;value&lt;/a&gt; of testing. However not all tests are equal, and actually not all tests provide value at all. Raise your hand if you’ve ever seen (unit) tests that tested every corner case of trivial piece of code that’s used once in a blue moon in an obscure part of the system. Raise your other hand if that test code was not written by human but generated.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;As with any type of code, test code is a liability. It takes time to write it, and then it takes even more time to read it and maintain it. Considering time is money, rather then blindly unit testing everything we need to constantly ask ourselves how do we get the best value for the money – what’s the best way to spend time writing code, to write the least amount of it, to best cover the widest range of possible failures in the most maintainable fashion.&lt;/p&gt;  &lt;p&gt;Notice we’re optimising quite a few variables here. We don’t want to blindly write plenty of code, we don’t want to write sloppy code, and we want the test code to properly fulfil its role as our safety net, alarming us early when things are about to go belly up.&lt;/p&gt;  &lt;h3&gt;Testing conventions&lt;/h3&gt;  &lt;p&gt;What many people seem to find challenging to test is conventions in their code. When all you have is a hammer (unit testing) it’s hard to hit a nail, that not only isn’t really a nail, but isn’t really explicitly there to being with. To make matters worse the compiler is not going to help you really either. How would it know that LoginController not implementing IController is a problem? How would it know that the new dependency you introduced onto the controller is not registered in your IoC container? How would it know that the public method on your &lt;a href="http://nhforge.org" target="_blank"&gt;NHibernate&lt;/a&gt; entity needs to be virtual?&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;In some cases the tool you’re using will provide some level of validation itself. NHibernate knows the methods ought to be virtual and will give you quite good exception message when you set it up. You can verify that quite easily in a simple test. Not everything is so black and white however. One of diagnostics provided by &lt;a href="http://docs.castleproject.org/Windsor.MainPage.ashx" target="_blank"&gt;Castle Windsor&lt;/a&gt; is called “&lt;strong&gt;Potentially&lt;/strong&gt; misconfigured components”. Notice the vagueness of the first word. They might be misconfigured, but not necessarily are – it all depends on how you’re using them and the tool itself cannot know that. How do you test that efficiently?&lt;/p&gt;  &lt;h3&gt;Enter approval testing&lt;/h3&gt;  &lt;p&gt;One possible solution to that, which we’ve been quite successfully using on my current project is approval testing. The concept is very simple. You write a test that runs producing an output. Then the output is reviewed by someone, and assuming it’s correct, it’s marked as approved and committed to the VCS repository. On subsequent runs the output is generated again, and compared against approved version. If they are different the test fails, at which point someone needs to review the change and either mark the new version as approved (when the change is legitimate) or fix the code, if the change is a bug.&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;If the explanation above seems dry and abstract let’s go through an example. Windsor 3 introduced way to programmatically access its diagnostics. We can therefore write a test looking through the potentially misconfigured components, so that we get notified if something on the list changes. I’ll be using &lt;a href="http://approvaltests.sourceforge.net/" target="_blank"&gt;ApprovalTests&lt;/a&gt; library for that.&lt;/p&gt;  &lt;div style="border-bottom:silver 1px solid;text-align:left;border-left:silver 1px solid;padding-bottom:4px;line-height:12pt;background-color:#f4f4f4;margin:20px 0px 10px;padding-left:4px;width:97.5%;padding-right:4px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;max-height:700px;font-size:8pt;overflow:auto;border-top:silver 1px solid;cursor:text;border-right:silver 1px solid;padding-top:4px;" id="codeSnippetWrapper"&gt;   &lt;div style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;background-color:#f4f4f4;border-left-style:none;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;border-right-style:none;font-size:8pt;overflow:visible;padding-top:0px;" id="codeSnippet"&gt;     &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;background-color:white;margin:0em;border-left-style:none;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;border-right-style:none;font-size:8pt;overflow:visible;padding-top:0px;"&gt;[Test]&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;border-left-style:none;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;border-right-style:none;font-size:8pt;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#0000ff;"&gt;public&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;void&lt;/span&gt; Approved_potentially_misconfigured_components()&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;background-color:white;margin:0em;border-left-style:none;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;border-right-style:none;font-size:8pt;overflow:visible;padding-top:0px;"&gt;{&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;border-left-style:none;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;border-right-style:none;font-size:8pt;overflow:visible;padding-top:0px;"&gt;    var container = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; WindsorContainer();&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;background-color:white;margin:0em;border-left-style:none;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;border-right-style:none;font-size:8pt;overflow:visible;padding-top:0px;"&gt;    container.Install(FromAssembly.Containing&amp;lt;HomeController&amp;gt;()); &lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;border-left-style:none;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;border-right-style:none;font-size:8pt;overflow:visible;padding-top:0px;"&gt;&amp;#160;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;background-color:white;margin:0em;border-left-style:none;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;border-right-style:none;font-size:8pt;overflow:visible;padding-top:0px;"&gt;    var handlers = GetPotentiallyMisconfiguredComponents(container);&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;border-left-style:none;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;border-right-style:none;font-size:8pt;overflow:visible;padding-top:0px;"&gt;    var message = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; StringBuilder();&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;background-color:white;margin:0em;border-left-style:none;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;border-right-style:none;font-size:8pt;overflow:visible;padding-top:0px;"&gt;    var inspector = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; DependencyInspector(message);&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;border-left-style:none;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;border-right-style:none;font-size:8pt;overflow:visible;padding-top:0px;"&gt;    &lt;span style="color:#0000ff;"&gt;foreach&lt;/span&gt; (IExposeDependencyInfo handler &lt;span style="color:#0000ff;"&gt;in&lt;/span&gt; handlers)&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;background-color:white;margin:0em;border-left-style:none;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;border-right-style:none;font-size:8pt;overflow:visible;padding-top:0px;"&gt;    {&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;border-left-style:none;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;border-right-style:none;font-size:8pt;overflow:visible;padding-top:0px;"&gt;        handler.ObtainDependencyDetails(inspector);&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;background-color:white;margin:0em;border-left-style:none;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;border-right-style:none;font-size:8pt;overflow:visible;padding-top:0px;"&gt;    }&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;border-left-style:none;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;border-right-style:none;font-size:8pt;overflow:visible;padding-top:0px;"&gt;    Approvals.Approve(message.ToString());&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;background-color:white;margin:0em;border-left-style:none;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;border-right-style:none;font-size:8pt;overflow:visible;padding-top:0px;"&gt;}&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;border-left-style:none;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;border-right-style:none;font-size:8pt;overflow:visible;padding-top:0px;"&gt;&amp;#160;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;background-color:white;margin:0em;border-left-style:none;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;border-right-style:none;font-size:8pt;overflow:visible;padding-top:0px;"&gt;&lt;span style="color:#0000ff;"&gt;private&lt;/span&gt; &lt;span style="color:#0000ff;"&gt;static&lt;/span&gt; IHandler[] GetPotentiallyMisconfiguredComponents(WindsorContainer container)&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;border-left-style:none;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;border-right-style:none;font-size:8pt;overflow:visible;padding-top:0px;"&gt;{&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;background-color:white;margin:0em;border-left-style:none;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;border-right-style:none;font-size:8pt;overflow:visible;padding-top:0px;"&gt;    var host = container.Kernel.GetSubSystem(SubSystemConstants.DiagnosticsKey) &lt;span style="color:#0000ff;"&gt;as&lt;/span&gt; IDiagnosticsHost;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;border-left-style:none;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;border-right-style:none;font-size:8pt;overflow:visible;padding-top:0px;"&gt;    var diagnostic = host.GetDiagnostic&amp;lt;IPotentiallyMisconfiguredComponentsDiagnostic&amp;gt;();&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;background-color:white;margin:0em;border-left-style:none;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;border-right-style:none;font-size:8pt;overflow:visible;padding-top:0px;"&gt;    var handlers = diagnostic.Inspect();&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;border-left-style:none;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;border-right-style:none;font-size:8pt;overflow:visible;padding-top:0px;"&gt;    &lt;span style="color:#0000ff;"&gt;return&lt;/span&gt; handlers;&lt;/pre&gt;


    &lt;pre style="border-bottom-style:none;text-align:left;padding-bottom:0px;line-height:12pt;background-color:white;margin:0em;border-left-style:none;padding-left:0px;width:100%;padding-right:0px;font-family:&amp;#39;Courier New&amp;#39;, courier, monospace;direction:ltr;border-top-style:none;color:black;border-right-style:none;font-size:8pt;overflow:visible;padding-top:0px;"&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;What’s important here is we’re setting up the container, getting the misconfigured components out of it, produce readable output from the list and passing it down to the approval framework to do the rest of the job.&lt;/p&gt;

&lt;p&gt;Now if you’ve set up the framework to pup-up a diff tool when the approval fails you will be greeted with something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/approval_5F00_diff_5F00_2.png"&gt;&lt;img style="border-right-width:0px;margin:5px 0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="approval_diff" border="0" alt="approval_diff" src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/approval_5F00_diff_5F00_thumb.png" width="640" height="388" /&gt;&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;You have all the power of your diff tool to inspect the change. In this case we have one new misconfigured component (HomeController) which has a new parameter, appropriately named missingParameter that the container doesn’t know how to provide to it. Now you either slap yourself in the forehead and fix the issue, if that really is an issue, or approve that dependency, by copying the diff chunk from the left pane to the right, approved pane. By doing the latter you’re notifying the testing framework and your teammates that you do know what’s going on and you know it’s not an issue the way things are going to work. Coupled with a sensible commit message explaining why you chose to approve this difference you get a pretty good trail of exception to the rule and reasons behind them.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;That’s quite an elegant approach to a quite hard problem. We’re using it for quite a few things, and it’s been giving us really good value for little effort it took to write those tests, and maintain them as we keep developing the app, and the approved files change.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;So there you have it, a new, useful tool in your toolbelt.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=69327" width="1" height="1"&gt;</description></item><item><title>API design challenge – builder</title><link>http://devlicio.us/blogs/krzysztof_kozmic/archive/2011/12/31/api-design-challenge-builder.aspx</link><pubDate>Sat, 31 Dec 2011 01:07:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:68884</guid><dc:creator>Krzysztof Koźmic</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/krzysztof_kozmic/rsscomments.aspx?PostID=68884</wfw:commentRss><comments>http://devlicio.us/blogs/krzysztof_kozmic/archive/2011/12/31/api-design-challenge-builder.aspx#comments</comments><description>&lt;p&gt;Now that &lt;a href="http://kozmic.pl/2011/12/16/castle-windsor-3-0-is-released/" target="_blank"&gt;Windsor 3 is released&lt;/a&gt; I can concentrate on some of my other ideas and projects. While working on one of them, &lt;a href="https://github.com/kkozmic/Cartographer" target="_blank"&gt;called Cartographer&lt;/a&gt;, I encountered an interesting API design problem.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;I have a class (a builder to be precise) that has a task of setting up a central object (an IMapper implementation) in Cartographer (If you&amp;rsquo;ve ever used &lt;a href="http://autofac.org" target="_blank"&gt;Autofac&lt;/a&gt;, it is somewhat analogous to ContainerBuilder). What is interesting about it, is I have three goals for that class:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Provide API for high level configuration and extension points that are universal to and intrinsic to any IMapper implementation.&lt;/li&gt;
&lt;li&gt;Provide API for low level configuration of the default IMapper implementation that the builder creates, that will meet the following criteria:&lt;ol&gt;
&lt;li&gt;Not force user to customize anything, as the default setup should be enough to get started in most cases.&lt;/li&gt;
&lt;li&gt;Allow users to easily swap/extend parts of the dependency chain of the default mapper.&lt;/li&gt;
&lt;li&gt;Work well and be natural both with and without IoC container .&lt;/li&gt;
&lt;/ol&gt;&lt;/li&gt;
&lt;li&gt;Be simple and discoverable to the users (and provide good Intellisense experience).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;How would you design the API for this class?&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Oh, and happy new year.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=68884" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/krzysztof_kozmic/archive/tags/Design/default.aspx">Design</category></item><item><title>Castle Windsor 3.0 is released</title><link>http://devlicio.us/blogs/krzysztof_kozmic/archive/2011/12/16/castle-windsor-3-0-is-released.aspx</link><pubDate>Fri, 16 Dec 2011 12:55:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:68848</guid><dc:creator>Krzysztof Koźmic</dc:creator><slash:comments>6</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/krzysztof_kozmic/rsscomments.aspx?PostID=68848</wfw:commentRss><comments>http://devlicio.us/blogs/krzysztof_kozmic/archive/2011/12/16/castle-windsor-3-0-is-released.aspx#comments</comments><description>&lt;p&gt;&lt;img style="border-right-width:0px;margin:5px 0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="Castle Windsor" alt="Castle Windsor" src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/wc_5F00_logo100_5B00_1_5D005F00_3.png" height="100" width="100" border="0" /&gt; &lt;/p&gt;
&lt;p&gt;After successful &lt;a href="http://kozmic.pl/2011/08/15/windsor-3-beta-1-is-released-along-with-other-goodies/" target="_blank"&gt;beta&lt;/a&gt; and &lt;a href="http://kozmic.pl/2011/11/20/getting-closer-castle-windsor-3-rc-1/" target="_blank"&gt;RC releases&lt;/a&gt; final version of &lt;a href="http://docs.castleproject.org/Windsor.MainPage.ashx" target="_blank"&gt;Castle Windsor&lt;/a&gt; (as well as Castle Core, and a whole set of facilities) has now been released. There are no major changes between final version and RC. The difference is some minor bug fixes, improved exception messages and some small improvements all over the place.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;The packages are available now, on &lt;a href="http://docs.castleproject.org/Windsor.MainPage.ashx" target="_blank"&gt;Nuget&lt;/a&gt; (with symbols), and via &lt;a href="http://sourceforge.net/projects/castleproject/files/Windsor/3.0/Castle.Windsor.3.0.0.zip/download" target="_blank"&gt;standard .zip download&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Last but not least - thank you to everyone who downloaded beta and release candidate and provided feedback. You guys rock.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=68848" width="1" height="1"&gt;</description></item><item><title>Getting closer… Castle Windsor 3 RC 1</title><link>http://devlicio.us/blogs/krzysztof_kozmic/archive/2011/11/20/getting-closer-castle-windsor-3-rc-1.aspx</link><pubDate>Sun, 20 Nov 2011 12:10:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:68406</guid><dc:creator>Krzysztof Koźmic</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/krzysztof_kozmic/rsscomments.aspx?PostID=68406</wfw:commentRss><comments>http://devlicio.us/blogs/krzysztof_kozmic/archive/2011/11/20/getting-closer-castle-windsor-3-rc-1.aspx#comments</comments><description>&lt;p&gt;Few weeks later than originally expected but here it is &amp;ndash; Castle Windsor 3.0 (along with its facilities and Castle.Core) achieved release candidate status.&lt;/p&gt;
&lt;p&gt;There is one major new feature in this release: registration API gained ability to specify properties to ignore/require. There are some scenarios where that&amp;rsquo;s useful, for example where integrating with some 3rd party framework that forces you to inherit from a base class which exposes its dependencies as properties. Creating pass-through constructors for each inherited class can be mundane. In those cases you can simply mark those base class properties as required, in which case Windsor will not allow them to be resolved unless all base property dependencies are satisfied. PropertyFilter enum supports several other most common scenarios, and for advanced cases there&amp;rsquo;s an overload that gives you more control.&lt;/p&gt;
&lt;div style="text-align:left;padding:4px;line-height:12pt;background-color:#f4f4f4;margin:20px 0px 10px;width:97.5%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;max-height:700px;font-size:8pt;overflow:auto;cursor:text;border:1px solid silver;" id="codeSnippetWrapper"&gt;
&lt;div style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;" id="codeSnippet"&gt;
&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;Container.Register(&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;    Classes.FromThisAssembly()&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;        .BasedOn&amp;lt;ICommon&amp;gt;()&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;        .Configure(c =&amp;gt; c.Properties(PropertyFilter.RequireBase)));&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;To address performance hit at startup Windsor no longer enables &lt;a href="http://docs.castleproject.org/Windsor.Performance-Counters.ashx" target="_blank"&gt;performance counters&lt;/a&gt; by default. Now, you have to do it explicitly:&lt;/p&gt;
&lt;div style="text-align:left;padding:4px;line-height:12pt;background-color:#f4f4f4;margin:20px 0px 10px;width:97.5%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;max-height:700px;font-size:8pt;overflow:auto;cursor:text;border:1px solid silver;" id="codeSnippetWrapper"&gt;
&lt;div style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;" id="codeSnippet"&gt;
&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;var container = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; WindsorContainer();&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;var diagnostic = LifecycledComponentsReleasePolicy.GetTrackedComponentsDiagnostic(container.Kernel);&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:white;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;var counter = LifecycledComponentsReleasePolicy.GetTrackedComponentsPerformanceCounter(&lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; PerformanceMetricsFactory());&lt;/pre&gt;

&lt;pre style="border-style:none;text-align:left;padding:0px;line-height:12pt;background-color:#f4f4f4;margin:0em;width:100%;font-family:&amp;#39;Courier New&amp;#39;,courier,monospace;direction:ltr;color:black;font-size:8pt;overflow:visible;"&gt;container.Kernel.ReleasePolicy = &lt;span style="color:#0000ff;"&gt;new&lt;/span&gt; LifecycledComponentsReleasePolicy(diagnostic, counter);&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Full changelog is included in the packages. Please, if possible, take the time to upgrade to this version and if you find any issues report them so that the final release is rock solid. If no major issues are found, the final release will be published in two weeks.&lt;/p&gt;
&lt;p&gt;The binaries are available on Nuget right now, and soon &lt;a href="http://castleproject.org/castle/projects.html" target="_blank"&gt;on our website&lt;/a&gt;.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=68406" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/krzysztof_kozmic/archive/tags/Castle/default.aspx">Castle</category><category domain="http://devlicio.us/blogs/krzysztof_kozmic/archive/tags/IoC/default.aspx">IoC</category></item><item><title>Connector: Simple, zero friction Github –&gt; AppHarbor integration</title><link>http://devlicio.us/blogs/krzysztof_kozmic/archive/2011/09/18/connector-simple-zero-friction-github-gt-appharbor-integration.aspx</link><pubDate>Sun, 18 Sep 2011 09:53:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:68184</guid><dc:creator>Krzysztof Koźmic</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/krzysztof_kozmic/rsscomments.aspx?PostID=68184</wfw:commentRss><comments>http://devlicio.us/blogs/krzysztof_kozmic/archive/2011/09/18/connector-simple-zero-friction-github-gt-appharbor-integration.aspx#comments</comments><description>&lt;p&gt;Recently to play with some new technology I came up with an idea to build an integration layer between Github and AppHarbor. What that means, is give you ability to work with your Github repository, reaping benefits of all of it’s VCS-centric features, and automatically, continuously deploy your code to AppHarbor.&lt;/p&gt;  &lt;p&gt;The actual scenario I had in mind is to be able to use that for deployment of Open Source projects. AppHarbor is fantastic, no-headache deployment in the cloud, but Github is perfect for keeping and developing your code in the open, in social way. To have the cake and eat it too, Connector was born.&lt;/p&gt;  &lt;p&gt;&lt;a href="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/Connector_5F00_2.png"&gt;&lt;img style="border-right-width:0px;margin:5px 0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="Connector" border="0" alt="Connector" src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/Connector_5F00_thumb.png" width="644" height="391" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;I hope you find it useful. it is free, use-at-your-own-risk-and-don’t-sue-me-if-something-breaks software. There’s still some work to be done, feature-wise and a whole lot of polishing but I decided to announce it early and get early feedback. If you have any suggestions, ideas or (gulp) bugs, let me know!&lt;/p&gt;  &lt;p&gt;link: &lt;a title="http://connector.apphb.com/" href="http://connector.apphb.com/"&gt;http://connector.apphb.com/&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Hope that helps.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=68184" width="1" height="1"&gt;</description></item><item><title>Windsor 3 beta 1 – dozen of Nuget packages and SymbolSource.org support</title><link>http://devlicio.us/blogs/krzysztof_kozmic/archive/2011/09/04/windsor-3-beta-1-dozen-of-nuget-packages-and-symbolsource-org-support.aspx</link><pubDate>Sun, 04 Sep 2011 10:47:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:68165</guid><dc:creator>Krzysztof Koźmic</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/krzysztof_kozmic/rsscomments.aspx?PostID=68165</wfw:commentRss><comments>http://devlicio.us/blogs/krzysztof_kozmic/archive/2011/09/04/windsor-3-beta-1-dozen-of-nuget-packages-and-symbolsource-org-support.aspx#comments</comments><description>&lt;p&gt;As &lt;a href="http://kozmic.pl/2011/08/15/windsor-3-beta-1-is-released-along-with-other-goodies/" target="_blank"&gt;promised&lt;/a&gt;, I released Nuget packages for beta 1 of Windsor 3. This is my first major rollout of Nuget packages, so please report any issues working with them.&lt;/p&gt;
&lt;h3&gt;Nuget and beta packages&lt;/h3&gt;
&lt;p&gt;Nuget is quickly evolving and getting more useful with each release. However one feature it&amp;rsquo;s missing right now is support for pre-release packages (&lt;a href="http://twitter.com/#!/davidebbo/status/109564923935330305" target="_blank"&gt;this is coming in the next version&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;a href="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/davidebbo_5F00_2.png"&gt;&lt;img style="border-bottom:0px;border-left:0px;display:inline;border-top:0px;border-right:0px;" title="davidebbo" alt="davidebbo" src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/davidebbo_5F00_thumb.png" border="0" height="350" width="613" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;This is not really a big deal, however it means there are a few things you should be aware of.&lt;/p&gt;
&lt;h3&gt;Recommended version&lt;/h3&gt;
&lt;p&gt;Since the new package is a pre-release, while I would really like for everyone to start using it immediately and report all issues they find, I quite understand that many people will rather prefer to stick to the last official version for the time being. To accommodate that the new packages are not made recommended versions, so your Nuget explorer will still point to the last stable (2.5.3) version if you search for Windsor, Castle.Core or any other pre-existing package.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/nuget_5F00_explorer_5F00_2.png"&gt;&lt;img style="border-bottom:0px;border-left:0px;display:inline;border-top:0px;border-right:0px;" title="nuget_explorer" alt="nuget_explorer" src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/nuget_5F00_explorer_5F00_thumb.png" border="0" height="450" width="800" /&gt;&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;If you go to command line and install one of the packages without specifying version number, it will install the latest, that is beta 1 version.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/nuget_5F00_commandline_5F00_2.png"&gt;&lt;img style="border-bottom:0px;border-left:0px;display:inline;border-top:0px;border-right:0px;" title="nuget_commandline" alt="nuget_commandline" src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/nuget_5F00_commandline_5F00_thumb.png" border="0" height="188" width="630" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;h3&gt;SymbolSource.org and debugging into Windsor&lt;/h3&gt;
&lt;p&gt;Folks at &lt;a href="http://www.symbolsource.org/" target="_blank"&gt;SymbolSource.org&lt;/a&gt; added recently support for Nuget (and &lt;a href="http://www.openwrap.org/" target="_blank"&gt;OpenWrap&lt;/a&gt; as well) and the new Castle packages take advantage of that. What it gives you, is you can now easily debug into Windsor&amp;rsquo;s code, just like .NET framework reference source (&lt;a href="http://www.symbolsource.org/Public/Home/VisualStudio" target="_blank"&gt;there&amp;rsquo;s a simple guide at SymbolSource on how to do it&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;After you&amp;rsquo;re all set you can step into any of Castle methods in your debugger and watch the magic happen. Very cool thing, even if I say so myself.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/windsor_2D00_source_2D00_debugging_5F00_2.png"&gt;&lt;img style="border-bottom:0px;border-left:0px;display:inline;border-top:0px;border-right:0px;" title="windsor-source-debugging" alt="windsor-source-debugging" src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/windsor_2D00_source_2D00_debugging_5F00_thumb.png" border="0" height="397" width="833" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;List of packages&lt;/h3&gt;
&lt;p&gt;Here&amp;rsquo;s the full list of v3 beta 1 packages (notice those are not all Castle packages, just those that were published as v3 beta 1 rollout of Windsor):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://nuget.org/List/Packages/Castle.Core" target="_blank"&gt;Castle.Core&lt;/a&gt; &amp;ndash; Contains Castle.Core.dll which includes DynamicProxy, DictionaryAdapter, EmailSender, logging abstractions and some other goodies.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://nuget.org/List/Packages/Castle.Core-log4net" target="_blank"&gt;Castle.Core-log4net&lt;/a&gt; &amp;ndash; Contains Castle.Services.Logging.Log4netIntegration.dll, that is implementation of Castle logging abstractions for log4net&lt;/li&gt;
&lt;li&gt;&lt;a href="http://nuget.org/List/Packages/Castle.Core-NLog" target="_blank"&gt;Castle.Core-NLog&lt;/a&gt; &amp;ndash; Contains Castle.Services.Logging.NLogIntegration.dll, that is implementation of Castle logging abstractions for NLog&lt;/li&gt;
&lt;li&gt;&lt;a href="http://nuget.org/List/Packages/Castle.Windsor" target="_blank"&gt;Castle.Windsor&lt;/a&gt; &amp;ndash; Contains Castle.Windsor.dll which has Windsor itself and two most commonly used facilities &amp;ndash; &lt;a href="http://docs.castleproject.org/Windsor.Typed-Factory-Facility.ashx" target="_blank"&gt;Typed Factory facility&lt;/a&gt; and &lt;a href="http://docs.castleproject.org/Windsor.Startable-Facility.ashx" target="_blank"&gt;Startable facility&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://nuget.org/List/Packages/Castle.LoggingFacility" target="_blank"&gt;Castle.LoggingFacility&lt;/a&gt; &amp;ndash; Contains &lt;a href="http://docs.castleproject.org/Windsor.Logging-Facility.ashx" target="_blank"&gt;logging facility&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://nuget.org/List/Packages/Castle.Windsor-log4net" target="_blank"&gt;Castle.Windsor-log4net&lt;/a&gt; &amp;ndash; Empty package that just installs logging facility and Castle.Core-log4net (and their dependencies obviously).&lt;/li&gt;
&lt;li&gt;&lt;a href="http://nuget.org/List/Packages/Castle.Windsor-NLog" target="_blank"&gt;Castle.Windsor-NLog&lt;/a&gt; &amp;ndash; Empty package that just installs logging facility and Castle.CoreNLog (and their dependencies obviously).&lt;/li&gt;
&lt;li&gt;&lt;a href="http://nuget.org/List/Packages/Castle.WcfIntegrationFacility"&gt;Castle.WcfIntegrationFacility&lt;/a&gt; &amp;ndash; Windsor&amp;rsquo;s &lt;a href="http://docs.castleproject.org/Windsor.WCF-Integration-Facility.ashx" target="_blank"&gt;WCF facility&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://nuget.org/List/Packages/Castle.SynchronizeFacility"&gt;Castle.SynchronizeFacility&lt;/a&gt; &amp;ndash; Windsor&amp;rsquo;s &lt;a href="http://docs.castleproject.org/Windsor.Synchronize-Facility.ashx" target="_blank"&gt;Synchronize facility&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="http://nuget.org/List/Packages/Castle.RemotingFacility"&gt;Castle.RemotingFacility&lt;/a&gt; &amp;ndash; Windsor&amp;rsquo;s &lt;a href="http://docs.castleproject.org/Windsor.Remoting-Facility.ashx" target="_blank"&gt;Remoting facility&lt;/a&gt; (extracted out of Castle.Windsor.dll)&lt;/li&gt;
&lt;li&gt;&lt;a href="http://nuget.org/List/Packages/Castle.EventWiringFacility"&gt;Castle.EventWiringFacility&lt;/a&gt; &amp;ndash; Windsor&amp;rsquo;s &lt;a href="http://docs.castleproject.org/Windsor.Event-Wiring-Facility.ashx" target="_blank"&gt;Event Wiring facility&lt;/a&gt; (extracted out of Castle.Windsor.dll)&lt;/li&gt;
&lt;li&gt;&lt;a href="http://nuget.org/List/Packages/Castle.FactorySupportFacility"&gt;Castle.FactorySupportFacility&lt;/a&gt;&amp;ndash; Windsor&amp;rsquo;s &lt;a href="http://docs.castleproject.org/Windsor.Factory-Support-Facility.ashx" target="_blank"&gt;Factory Support facility&lt;/a&gt; (extracted out of Castle.Windsor.dll)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;I hope this will make it easier for everyone to test drive Windsor. And if you find any issues, have any suggestions or ideas, do not hesitate to bring them up, either on our &lt;a href="http://groups.google.com/group/castle-project-users" target="_blank"&gt;google group&lt;/a&gt;, or &lt;a href="http://issues.castleproject.org/dashboard" target="_blank"&gt;issue tracker&lt;/a&gt;.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=68165" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/krzysztof_kozmic/archive/tags/Castle/default.aspx">Castle</category></item><item><title>Simple guide to running Git server on Windows, in local network (kind of)</title><link>http://devlicio.us/blogs/krzysztof_kozmic/archive/2011/08/20/simple-guide-to-running-git-server-on-windows-in-local-network-kind-of.aspx</link><pubDate>Sat, 20 Aug 2011 07:50:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:68118</guid><dc:creator>Krzysztof Koźmic</dc:creator><slash:comments>6</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/krzysztof_kozmic/rsscomments.aspx?PostID=68118</wfw:commentRss><comments>http://devlicio.us/blogs/krzysztof_kozmic/archive/2011/08/20/simple-guide-to-running-git-server-on-windows-in-local-network-kind-of.aspx#comments</comments><description>&lt;p&gt;Last year I found myself in a sudden and quick need to set up working environment for a team of four, and as I like Git very much, I wanted to use it as our VCS. The problem was, we weren&amp;rsquo;t allowed to use any third party provider, so GitHub was off the table. As I searched the Internet there were a few guides to set up team Git environment on Windows, but they all seemed very complicated and time consuming. For our modest needs we experimented a little and came up with a solution that was very simple, didn&amp;rsquo;t require any additional software to be installed anywhere and worked like a charm.&lt;/p&gt;
&lt;p&gt;Recently I used it again on my current engagement, and one of my colleagues suggested I should blog it, so here goes.&lt;/p&gt;
&lt;h3&gt;Ready, steady, go&lt;/h3&gt;
&lt;p&gt;The guide assumes you already have your local Git set up. For that, there are plenty of resources on the Internet, including &lt;a href="http://kozmic.pl/2011/01/26/git-tooling-for-net-developers/" target="_blank"&gt;my own blogpost about Windows Git tooling&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The entire tricks works like this &amp;ndash; expose folder containing your shared Git repository as Windows network share.&lt;/p&gt;
&lt;h3&gt;Step one &amp;ndash; bare git repository&lt;/h3&gt;
&lt;p&gt;There are two twists to the entire solution &amp;ndash; one of them is &amp;ndash; your shared repository needs to be initialized with --bare flag.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/git_5F00_bare_5F00_repository_5F00_2.png"&gt;&lt;img style="border-right-width:0px;margin:5px 0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="git_bare_repository" alt="git_bare_repository" src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/git_5F00_bare_5F00_repository_5F00_thumb.png" height="375" width="644" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;h3&gt;Step two &amp;ndash; Windows share&lt;/h3&gt;
&lt;p&gt;Second step is to expose the folder with our newly created repository on the Windows share. You also use your standard Windows mechanisms to control and limit access to the folder (make sure you give the developers write access!).&lt;/p&gt;
&lt;h3&gt;Step three &amp;ndash; Map the share as network drive&lt;/h3&gt;
&lt;p&gt;This step is perhaps not exactly necessary but I couldn&amp;rsquo;t get it to work otherwise, so here comes the second twist. In order for your developers to be able to access the shared folder via Git they need to map it as network drive.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/sshot_2D00_10_5F00_2.png"&gt;&lt;img style="border-right-width:0px;margin:5px 0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="sshot-10" alt="sshot-10" src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/sshot_2D00_10_5F00_thumb.png" height="464" width="632" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;h3&gt;Step four &amp;ndash; Add remote repository in Git and code away&lt;/h3&gt;
&lt;p&gt;Last step is the standard Git procedure &amp;ndash; every developer on your team needs to add the repository sitting under their newly created network drive as remote. Notice the use of &amp;ldquo;file:///&amp;rdquo; prefix in front of the mapped drive name.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/sshot_2D00_11_5F00_2.png"&gt;&lt;img style="border-right-width:0px;margin:5px 0px;display:inline;border-top-width:0px;border-bottom-width:0px;border-left-width:0px;" title="sshot-11" alt="sshot-11" src="http://devlicio.us/cfs-file.ashx/__key/CommunityServer.Blogs.Components.WeblogFiles/krzysztof_5F00_kozmic/sshot_2D00_11_5F00_thumb.png" height="375" width="644" border="0" /&gt;&lt;/a&gt; &lt;/p&gt;
&lt;h3&gt;&lt;/h3&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;Step five&lt;/h3&gt;
&lt;p&gt;That&amp;rsquo;s all. I hope you find it useful, and if you know a way to eliminate step three, let me know in the comments.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=68118" width="1" height="1"&gt;</description></item><item><title>Windsor 3 beta 1 is released (along with other goodies)</title><link>http://devlicio.us/blogs/krzysztof_kozmic/archive/2011/08/15/windsor-3-beta-1-is-released-along-with-other-goodies.aspx</link><pubDate>Mon, 15 Aug 2011 10:49:00 GMT</pubDate><guid isPermaLink="false">40756a8b-6212-4073-9d98-6c26781577de:68106</guid><dc:creator>Krzysztof Koźmic</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://devlicio.us/blogs/krzysztof_kozmic/rsscomments.aspx?PostID=68106</wfw:commentRss><comments>http://devlicio.us/blogs/krzysztof_kozmic/archive/2011/08/15/windsor-3-beta-1-is-released-along-with-other-goodies.aspx#comments</comments><description>&lt;p&gt;&lt;img src="http://castleproject.org/images/wc_logo.png" alt="" /&gt;&lt;/p&gt;
&lt;p&gt;The title says it all. If you can&amp;rsquo;t wait grab the binaries &lt;a href="http://sourceforge.net/projects/castleproject/files/Windsor/3.0/Castle.Windsor.3.0.0.beta1.zip/download%20" target="_blank"&gt;here (Windsor with Castle Core and facilities)&lt;/a&gt; and &lt;a href="http://sourceforge.net/projects/castleproject/files/Core/3.0/Castle.Core.3.0.0.beta1.zip/download" target="_blank"&gt;here (just Core)&lt;/a&gt;. Nuget package will hopefully follow soon.&lt;/p&gt;
&lt;h3&gt;What&amp;rsquo;s in it?&lt;/h3&gt;
&lt;p&gt;This is a major release and there&amp;rsquo;s quite a lot of new features, as well as some significant changes under the covers. &lt;a href="http://docs.castleproject.org/Windsor.Whats-New-In-Windsor-3.ashx" target="_blank"&gt;There&amp;rsquo;s a high level overview of highlights for the release in the wiki&lt;/a&gt;, so please have a look there. More detailed changelog, and list of breaking changes is available as part of the package.&lt;/p&gt;
&lt;p&gt;Remember it&amp;rsquo;s a beta release. Documentation and samples are still being updated and some features are not yet implemented or not fully baked. However it is very important that you don&amp;#39;t wait for the final release to upgrade, so that we can find and fix all the issues before final release. I&amp;#39;m not asking you to use it in production, but I&amp;#39;d really appreciate if you&amp;#39;d take the time to branch your apps, try to upgrade, run your unit tests, play with new version, and report any issues you may find. And ask your colleagues, friends and random people on the street to do the same!&lt;/p&gt;
&lt;p&gt;And if you find any issues, &lt;a href="http://issues.castleproject.org" target="_blank"&gt;do report them&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;   &lt;br /&gt;Have fun and happy coding,     &lt;br /&gt;I hope you like it&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://devlicio.us/aggbug.aspx?PostID=68106" width="1" height="1"&gt;</description><category domain="http://devlicio.us/blogs/krzysztof_kozmic/archive/tags/Castle/default.aspx">Castle</category><category domain="http://devlicio.us/blogs/krzysztof_kozmic/archive/tags/.NET/default.aspx">.NET</category><category domain="http://devlicio.us/blogs/krzysztof_kozmic/archive/tags/IoC/default.aspx">IoC</category></item></channel></rss>