thoughts on coding

May 16, 2013

Moving the blog

Filed under: Uncategorized — Frantisek @ 5:26 pm

Moving my blog to http://blogs.msdn.com/b/fkaduk

August 16, 2011

Porting a WPF App with MVVM Design Pattern to Silverlight 4 using Caliburn, FluentValidation

Filed under: .NET, Caliburn, FluentValidation, Silverlight, Uncategorized, WPF/Silverlight — Frantisek @ 7:04 am

There is a demo application from Josh Smith showing usage of M-V-VM pattern in WPF. It’s taken as WPF MVVM foundation and it was published in MSDN magazine here: http://msdn.microsoft.com/en-us/magazine/dd419663.aspx [DemoApp1]

There is another blog entry describing how to migrate it into Silverlight 4 here: http://edventuro.us/2010/03/porting-a-wpf-app-with-the-model-view-viewmodel-design-pattern-to-silverlight-4/ [DemoApp2]

Because of our current project I work on a proof-of-concept for a smart client based on  SL4, I used the demo application as a basement and I rewrote it using Caliburn (as an application framework) and FluentValidation (for hte client side validation).

The main differences against the ported demo application [DemoApp2] are:

View resolution/instantiation based on the view-model class types. The idea behind the scene is that the viewmodels are prohibited to talk to any UI specific part and views ( View -> ViewModel/View, ViewModel -> View). When it’s necessary to open another view from the view model, we “activate” the viewmodel or return a subroutine result (a similar concept as with ASP.NET MVC and their ActionResult).

Then it’s necessary to bind the active viewmodel to display a content control in UI.

In this case Caliburn tries to locate some view (based on a convention) to display/present the active viewmodel. You can find more info about it on http://caliburn.codeplex.com/documentation.

The next IMHO improvement is the messaging mechanism in Caliburn. In other words, the messaging is the mechanism how to call any method on viewmodel from the view or how to send a message from the view to the viewmodel. This mechanism replaces usage of commands together with any interactivity definitions (attaching to the event and reacting). More info can be found here:  http://caliburn.codeplex.com/documentation. I used it for displaying and handling the list of the menu links.

The viewmodel instatiates the list of the actions.

We bind then the model of the messages to the view like following

The last but not least part is the  validation on the client side. A little bit background note: There are 3 different types of the validations:

a) UI validation (in SL done via IDataErrorInfo internface)

b) ViewModel input validation/handling, navigating the user to input the correct data

c) model validation

In Josh’s demo application the viewmodel copies the model’s properties and wraps them +  the validation logic spreads among viewmodel and models. Yes, models contains the data, notifications and plus the validation (which could contain the multilanguage support). I think, this is breaking the separation of concerns and that’s the reason I usedFluentValidation to do the validation => I separated the validation concern into the special class(es) with the suffix Validator.

It looks like Silverlights was designed with Close/Close principle (many classes are sealed, internal methods, internal constructors) there are very few parts which we can extend (binding, validation, validation errors, etc. – all are very tightly coupled from the extension point of the view).

So we need to follow stander IDataErrorInfo mechanism to UI support validation. So every model class will need to implement IDataErrorInfo. I had to separate Silverlight infrastructure code into a base class called ValidatableModelBase  and my models derive from it. That’s the way where model is not disturbed very much by IDataErrorInfo specifics.

ViewModel exposes a model, called subject.  ViewModelValidator<TViewModel> then enables ViewModel properties and their child to be validatable (fullfulling the UI requirements).

[class model]

It’s a concern of the viewmodel validator to decide what (what properties)  and when will be validated.

Then ViewModel or any model class is able to validate its properties and return the error message (supporting the multilanguage).

 

ViewModel (as a validation root) validate method:

 

The main Validation goals I wanted to fullfill:

a) do not drive the validation by throwing the exceptions

b) viewmodels shouldn’t copy the model properties and wrap them. It increases the amount of the code and complexity in more advanced scenarios

c) models should only hold the data and inform about their changes (INotifyPropertyChanged). Unfortunatelly, they need also derive from the base class which provides the infrastructure code (IDataErrorInfo).

The validation is bigger part and I’d like to provide an additional blog entry only about the validation.

What blog entries will follow:

  • connecting the server side with Agatha [preffered] or RRSL Lite in order to communicate with the server + generating the models (entities) for the view model
  • unit testing of the client side
  • finalizing the server side
  • enhancing the client/server with tracing and logging
  • client side and server side validation

You can download the code here: MvvmSilverlightDemoApp.zip (after downloading remove the extension txt)

 

April 5, 2011

NDepend for analyzing the design quality of code

Filed under: NDepend, Uncategorized — Tags: , , , , , — Frantisek @ 9:11 pm

I came back to a project I worked on 5 years ago. It was quite “interesting” to see the code after such long pause. We had to extend the application with few new features but I wanted to make sure the code is upgraded to higher code quality level. But it’s necessary to have some facts which will prove the higher code quality.

I decided to use NDepend for it. NDepend does the static code analyze. FXCop does the similar thing BUT! NDepend creates its own DB of the metrics/data gathered from the analyzed source code. You can query the data using CQL (code query language) or you can check few charts made by NDepend. CQL is also used to build the rules which could be evaluated to ensure good degree of code quality. It’s possible to use it using while continues integration process.

But there is one essential requirement! You need to be familiar with all the code metrics and CQL. You can find the detailed info about the metrics here. It took me a while to understand (I say “to feel”) them almost all.

GRAPHS


From my point of the view the graphs are the first parts which gets the user’s focus. One of the most usefull graphs is the Abstractness vs. Instability graph (AvI graph). If you want to understand the metrics more in deep, read this.

There is another blog post here which displays the “evolution” of the understanding of the code/metrics for AvI graph. Igloocoder shows what are the most important changes to his code in order to increase the code quality. He drives you through the changes and he finished with not very successful results because the refactored assembly didn’t end-up in the “green area”.

Just to clarify the goals of the graph:

  1. The goal is to end-up in the green area.
  2. split the assembly roles:
    • the abstract stable assembly – the assembly with high abstraction level and with very stable contract, used by many other assemblies
    • the concrete instable assembly – the assembly with very much of the concrete implementations and which are the area of the change with smaller direct usability => that’s the reason why it’s called instable = more probable to change

Igloo’s code end-up with the refactored code located in 1 assembly and the result is:

Unfortunately he didn’t do the final step. AvI graph is about the assemblies. So I tried to finish his analyze.
If we move the interfaces into a special so-called contract assembly then we get the following solution:

NDepend will generate for us the next graph:

If we remove the code analyze of the tests and exclude ALL system assemblies from the code analyze (I call it “we clean up the noisy assemblies) then we end-up with the ideal situation:

So Igloocoder was very close to the final solution.

If you want to know how the graphs are created it’s necessary to use and understand CQL. You can query and analyze the code metrics on different levels, e.g. assemblies, namespaces, types, types.

Here is the query which I used to analyze the instability metrics for the interfaces. The result grid displays as many collumns as WHERE clauses you write into CQL query.

As you can see NDepend measures Ce (aka efferent coupling) including references to the types from system assemblies, e.g. mscorlib. From my point of the view I’d like to clean up such MUST references and don’t include them into the measurements. It’s possible to do it when you manually change the configuration NDepend created for you. Here it is:

After that the AvI graph looks like the following:

That’s all for now. We are going to include NDepend measurements into our CI process just to have a view over our code.

February 28, 2011

Entity Framework: logging

Filed under: .NET, Entity Framework, Uncategorized — Tags: , , — Frantisek @ 11:25 am

I use EF4 CTP5 and I’d like to log ANY!!! SQL commands sent to the DB. You can use the method ToTraceString() to display the SQL commands of any ObjectQuery, but … you are not able to see the queries generated i.e. while saving changes OR lazy loading. You need to use i.e. EFProfiler to log it. EFProfiler is very cool tool but … I need to log it by my application.

So I found out the Tracing and Caching implementation by Jaroslaw Kowalski here which extends EF with tracing/logging and caching capabilities. The main disadvantages I found out are:
a) you need to you both! features otherwise logging/tracing will not work. I wanted to use only logging! After doing so I started to get strange exception (or I had to do something wrong). After enabling also tracing, it started to work. Shame because I needed to use ONLY tracing.
b) your Context classes HAS to be derived from his special classes.

Honestly, I don’t use this solution. It’s too much work.

MS guys, I’m sorry but I must say: IT’S BIG SHAME EF WAS NOT DEVELOPED IN EASY EXTENSIBLE MANNER with i.e. ServiceLocator, interceptors, etc. in place.

As far as I know, and correct me if I’m wrong, adding logging capabilities fits to AOP interceptors.

I.e. EFProfiler has quite hardly injects itself into creating new DB connection logic and then it has a capability to log everything. Their solution is more transparent than a by Mr. Kowalski.

My solution
I used the ideas from NHProfiler and I generalized it little bit. I made base AOP filter called IAopFilter.

public interface IAopFilter

    {

        void CommandDurationAndRowCount(Guid connectionId, long milliseconds, int? rowCount);

        void ConnectionDisposed(Guid connectionId);

        void ConnectionStarted(Guid connectionId);

        void DtcTransactionCompleted(Guid connectionId, TransactionStatus status);

        void DtcTransactionEnlisted(Guid connectionId, IsolationLevel isolationLevel);

        void StatementError(Guid connectionId, Exception exception);

        void StatementExecuted(Guid connectionId, Guid statementId, string statement);

        void StatementRowCount(Guid connectionId, Guid statementId, int rowCount);

        void TransactionBegan(Guid connectionId, System.Data.IsolationLevel isolationLevel);

        void TransactionCommit(Guid connectionId);

        void TransactionDisposed(Guid connectionId);

        void TransactionRolledBack(Guid connectionId);

    }

Due to the short of the time, I made only 1 its implementation and it was using Log4Net capabilities. Then I had to create AOP capable DbProviderFactory class called DbProviderFactoryEx which uses IAopFilters. In addition I had to create whole family of the classes following abstract factory pattern implemented in DbProviderFactory.

The main class is called EntityFrameworkExtender. This class wires-up AOP capabilities into EF. You just need to call:
EntityFrameworkExtender.Initialize();

The class by default uses Log4NetFilter as only the one filter but you can freely configure it.

EntityFrameworkExtender.Filters = () => new[] {new Log4NetFilter(“MyClass”)};

            EntityFrameworkExtender.Initialize();

Using it you are able transparently trace/log every SQL command sent from EF to DB.

I think, we, EF users would profit very much IF the EF team would develope the framework on enterprise level – easily extensible, configurable and if we could get also the unit tests! together with the framework.

[UPDATED!]
I bundled the whole source code into 1 project. The whole source code can be found here – save it as a file to the local disk  and delete .doc extension. It’s  normal zip file.
To use it you will need: log4net 1.2.10.0, EF4 CTP5, .NET 4.0

February 25, 2011

Entity Framework: Problem/Solution of default connection closing !

Filed under: .NET, Entity Framework, NCommon, StructureMap, Uncategorized — Tags: , — Frantisek @ 11:05 pm

I use EF CTP5 on my last project together with NCommon and its UnitOfWork, Repositories, IoC and DI abstracted by MS P&P team and StructureMap as the concrete implemetation of IoC and DI.

Problem :
Let’s have the following example (I took the example from the NCommon unit tests and extend it to do the same Linq query twice):

using (var scope = new UnitOfWorkScope())

{

    var repository = new EFRepository<User>();

 

    User user;

    user = repository.Where(u => u.ComsiID == "login").FirstOrDefault();

    user = repository.Where(u => u.ComsiID == "login").FirstOrDefault();

 

}

 

Just for the completion: creating new UnitOfWorkScope starts the DB transaction. In the above example, using UnitOfWork we create and start the transaction. Then we create new EFRepository instance which creates the ObjectContext. ObjectContext uses the connection identified by the same name AppDb and handles the connection on its own. Then we query the DB. EF opens the connection (this implies that the connection is enlisted into the current running transaction), reads the data and then close the connection. Fine! But then next (in this demo case) same query does the same: opens the connection. Because we run inside the transaction, so the connection is also enlisted into the transaction. And because there was already enlisted connection the transaction mechanism propagates it into DTS.

The result of the above code is that it works and sometimes not! The exception is following:
System.Data.EntityException: The underlying provider failed on Open.
---> System.InvalidOperationException: The connection object can not be enlisted in transaction scope.



THE PROBLEM IS IN ENTITY FRAMEWORK!!!!! and the result of the test depends on the underlying DB. If you use SQLExpress edition (as is used by default in NCommon unit tests), everything works fine! SQLExpress can not elevate the transaction to MS DTC. But if you change the connection to the real SQL server you starts to have the problems.

The problem is that in case you don’t send the concrete connection instance to EF, EF handles the connection status on his own => closes as soon as possible. I understand it but in case of Transaciton is fails! It would be good to have there a switch to configure that behavior. Anyway, the reality is different so how to fix it.

The solution is to manage the connection by your own and while creating the ObjectContext pass already created and open connection. You can find many examples about it on the internet.

Hm, fine but … not so nice. You need manually on all places where ObjectContext, or your class derived from ObjectContext, is used to manage the connection

With NCommon and it’s configuration capabilities you can do the following:

NCommon.Configure.Using(adapter)

    .ConfigureData<EFConfiguration>(config => config.WithObjectContext(

        () =>

        {

            AppDb db = new AppDb();

            if (Transaction.Current != null)

            {

                db.Connection.Open();

            }

            return db;

        }))

.ConfigureUnitOfWork<DefaultScopeUnitOfWorkConfiguration>();

 

 

So you don’t need to do open the connection over and over and on different places. Just configure NCommon on one place and use it. That’s the power of the centralized factory code-enabled configurations. In this case, thanks to StructureMap and NCommon!


Here is my full unit test class (using MS Tests):

[TestClass]

    public class SimpleTests

    {

        public IServiceLocator MyServiceLocator;

 

        [TestInitialize]

        public void Setup()

        {

            var _state = new FakeState();

            var _unitOfWorkFactory = new EFUnitOfWorkFactory();

            var _connectionString = ConfigurationManager.ConnectionStrings["AppDb"].ConnectionString;

            _unitOfWorkFactory.RegisterObjectContextProvider(

                () =>

                        {

                            var ctx = new AppDb(_connectionString);

                            if (Transaction.Current != null)

                            {

                                ctx.Connection.Open();

                            }

                            return ctx;

                        });

            var _locator = MockRepository.GenerateStub<IServiceLocator>();

            _locator.Stub(x => x.GetInstance<IUnitOfWorkFactory>()).Return(_unitOfWorkFactory);

            _locator.Stub(x => x.GetInstance<IState>()).Do(new Func<IState>(() => _state));

            ServiceLocator.SetLocatorProvider(() => _locator);

        }

 

        [TestCleanup]

        public void Cleanup()

        {

        }

 

        [TestMethod]

        public void Can_perform_simple_query()

        {

                using (var scope = new UnitOfWorkScope())

                {

                    var repository = new EFRepository<User>();

 

                    User user;

                    user = repository.Where(u => u.ComsiID == "a").FirstOrDefault();

                    user = repository.Where(u => u.ComsiID == "a").FirstOrDefault();

 

                }

        }

I must again say, NCommon and StructureMap rocks!

Happy coding…

February 24, 2011

NCommon: read-only operations = Unit Of Work without DB transaction

Filed under: .NET, NCommon, Uncategorized — Tags: — Frantisek @ 10:10 pm

Using NCommon I found one feature which can be an issue in some cases.

Repository can ONLY be used when you started an unit of work around it. Example:

using (var scope = new UnitOfWorkScope())

            {

                var savedCustomer = new EFRepository<Customer>()

                    .First(x => x.CustomerID == customer.CustomerID);

                scope.Commit();

            }

When new unit of work is created then it automatically starts the database transaction in the mode ReadCommited. Issue is that in case I need ONLY to read a data then I think, it’s too heavy. In other words why to pay the performance costs of creating a transaction when I want only to read the data from DB. In the default NCommon implementation this wouldn’t work:

var savedCustomer = new EFRepository<Customer>()

                    .First(x => x.CustomerID == customer.CustomerID);

I think it would be good avoid creating the DB transactions in case of read-only queries. It’s quite generic/DB-provider independed functionality so it fits into the base NCommon Repository classes. Unfortunatelly, I didnt want to change the base classes because in case new NCommon is releases and I changed the core functionality then I need to be in sync with latest NCommon verions. So I created my derived implementation for Entiry Framework v4. If there is no unit of the work created I create a single call unit of work without any transaction. Again, I think the change should be in the base NCommon classes but I wanted to stay compactible with the base classes as much as possible so I changed only the concrete Repository implementation for Entity Framework.

So using my changes the previous example works!

What do u think?

The changed NCommon for EFv4 can be found here

February 21, 2011

EFv4 with Repository and UnitOfWork pattern, IoC, DI

Filed under: Di Factory, IoC, NCommon, Uncategorized — Tags: — Frantisek @ 9:33 pm

Entity Framework itself implements unit of work pattern in form of the ObjectContext class. That’s fine but it has the following main disadvantages:
a) if you will use it from your business layer then you will be very tightly connected to the concrete DB layer implementation (in this case Entity Framework)
b) it will be much harder or impossible to do TDD.

It’s good practice to wrap the data access logic using Repository pattern. In other words it’s good to use the Repository pattern in order to abstract out/decouple the business layer from the data access layer. Fine, there is one Repository patter definition but many implementers and you can implement it also by your own. The basic idea is the same but many slightly different implementations.

When you work on different projects developed by the different people it’s good to establish enterprise-wide implementation of any common patterns/areas. Additionaly, it would be better if ti would be world-wide known implementation. So that’s NCommon which you can find on ncommon.codeplex.com.

NCommon provides, we could say, abstraction of the common programming areas like Repository, UnitOfWork, Guards, States, etc. In this entry I’ll focus on Repository.

NCommon provides the abstract Repository implementation – independent from any specific/concrete DB access implementation PLUS it contains implementations for Entity Framework, NHibernate, Db4O, etc. All specific implementations are located in its own projects. The advantage is that you can use out of the box implementation of your favorite implementation.

In addition, the base abstract Repository class offers LINQ provider on Class Level, not property level. Honestly, I like it ;o). Here is a sample:

using (var scope = new UnitOfWorkScope())

{

    var savedCustomer = new EFRepository<Customer>()

        .First(x => x.CustomerID == customer.CustomerID);

    scope.Commit();

}

 

In addition the base NCommon Repository classes are tightly connected with UnitOfWork pattern which is also abstracted into NCommon in form of UnitOfWork classes. You can get it also out of the box together with the different DB access specific implementations!

The unit of work implementation IS NOT ONLY 1 CONNECTION specific but spreads over different repositories and over different DB connections (if it’s your case). In other words, you can have i.e. a users repository implemented by NHibernate and connecting to UsersDB and OrdersRepostory implemented via EntiryFramework connecting to OrdersDB and the following example works:

In other words, one connection transaction will be elevated to the distributed transaction transparently and automatically. I like it! It seems to me really robust.

ALL is supported by standard service locators implemented by Microsoft Patterns and Practices team and with the NUnit tests!

I think, NCommon is really cool set of classes which collects the common aspects you will face while development. It’s really worth studying it! Here is a list of the links you can use:

Anyway, cool way how to check the latest library description is to look at the unit tests from GitHub.

Happy common coding !

August 12, 2010

MVCContrib extension – Localized Labels, Description

Filed under: ASP.NET MVC, MVCContrib, Uncategorized — Frantisek @ 2:17 pm

I use MVCContrib library on one of my ASP.NET MVC 2 projects. That project should have multi-language support. I use InputBuilders quite much but InputBuilders don’t support the multilanguage features for i.e. Labels, Descriptions, etc..

So I realized to extend it.

So to fully understand this blog entry you nee to be familiar with MvcContrib InputBuilders and the way how the default multi-language support is done in ASP.NET MVC.

There is quite nice article written about the localization here. There are several ways how to store the multi-language texts but I like Adam’s guide because it’s quite easy.

My MVCContrib-multi-language extension

In my project I have the source code of MVCContrib, so it was easy to extend. I demonstrate my extension on Labels.

I created 2 classes:

    1 namespace MvcContrib.UI.InputBuilder.Attributes

    2 {

    3     public class LabelAttribute : Attribute

    4     {

    5         public Type LabelResourceType { get; set; }

    6         public string LabelResourceName { get; set; }

    7 

    8         private string _label;

    9 

   10         public string Label

   11         {

   12             get

   13             {

   14                 if (!string.IsNullOrEmpty(_label))

   15                 {

   16                     return _label;

   17                 }

   18 

   19                 if (LabelResourceType != null && !string.IsNullOrEmpty(LabelResourceName))

   20                 {

   21                     PropertyInfo property = LabelResourceType.GetProperty(LabelResourceName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Static);

   22                     if (property != null)

   23                     {

   24                         var txt = property.GetValue(null, null) as string;

   25                         return txt;

   26                     }

   27                     return "Default:" + LabelResourceName;

   28                 }

   29 

   30                 return "";

   31             }

   32             set

   33             {

   34                 _label = value;

   35             }

   36         }

   37 

   38         public LabelAttribute()

   39         {

   40         }

   41 

   42         public LabelAttribute(string text)

   43         {

   44             Label = text;

   45         }

   46 

   47         public LabelAttribute(Type textResourceType, string textResourceName)

   48         {

   49             LabelResourceType = textResourceType;

   50             LabelResourceName = textResourceName;

   51         }

   52 

   53     }

   54 

   55     [AttributeUsage(AttributeTargets.Class)]

   56     public class LabelConventionAttribute : Attribute

   57     {

   58         public Type ResourceType { get; set; }

   59         public string Pattern { get; set; }

   60 

   61         public LabelConventionAttribute(Type resourceType, string pattern)

   62         {

   63             ResourceType = resourceType;

   64             Pattern = pattern;

   65         }

   66 

   67         public string GetLabelFor(string propertyName)

   68         {

   69             return new LabelAttribute(ResourceType, string.Format(Pattern, propertyName)).Label;

   70         }

   71     }

   72 }

Class LabelAttribute is to add the multilanguage support for the particular property. But because I’m lazy to write it on all properties of my model which is sent to the view, I create LabelConventionAttribute.

I like Convetion-over-Configuration style so using this attribute it is possible to setup the convention that the labels will be named by the convention Pattern.FormatWith(propetyName).

Next change was to change DefaultProperyConvention class to be partial. It’s due to the have my extensions in a separate class. I had to add there a method Lable

So here it’s

    1 namespace MvcContrib.UI.InputBuilder.Conventions

    2 {

    3     public partial class DefaultProperyConvention

    4     {

    5        

   17 

   18         public virtual string LabelForPropertyConvention(PropertyInfo propertyInfo)

   19         {

   20             if (propertyInfo.AttributeExists<LabelAttribute>())

   21             {

   22                 return propertyInfo.GetAttribute<LabelAttribute>().Label;

   23             }

   24             if (propertyInfo.ReflectedType.AttributeExists<LabelConventionAttribute>())

   25             {

   26                 return propertyInfo.ReflectedType.GetAttribute<LabelConventionAttribute>().GetLabelFor(propertyInfo.Name);

   27             }

   28             return propertyInfo.Name.ToSeparatedWords();

   29         }

   30     }

   31 }

   32 

And in the original DefaultPropertyConvention class I had to remove the method LabelForPropertyConvention.

That’s all. The similar steps can be done also for Description, but it’s necessary to extend PropertyViewModel class with new property.

The usage is:

    1 [DescriptionConvention(typeof(Descriptions), "Car_{0}")]

    2 [LabelConvention(typeof(Labels), "Car_{0}")]

    3 public class CarInput

    4 {

    5     [Required]

    6     [Example("BMW")]

    7     public virtual string Name { get; set; }

    8 }

Based on Adam’s guidance, I also had to create a resource file for the labels and the VS.NET created me the class Labels.

If you use MVCContrib builders then i.e. their Field.Master contains code like this: Html.Encode(Model.Label) to display the model’s label. Using the previously described extension it will be translated into the culture set in Thread.CurrentThread.CurrentUICulture.

That’s all for now …

August 11, 2010

Book Review: ASP.NET MVC 2 IN ACTION

Filed under: ASP.NET MVC, Di Factory, IoC, MVCContrib, NHibernate, StructureMap, Uncategorized — Frantisek @ 1:36 pm

I read MEAP version of the book ASP.NET MVC 2 in Action from Jeffrey Pallermo last month and I’d like to share my point of the view.

The book shows you how to use ASP.NET MVC 2 in Alt.Net (StuctureMap, MvcContrib, Rhino.Mocks, jQuery, NHibernate, NUnit, etc.) way – which I appreciate very much.

The book shows more how CodeCampServer.org was built connected with ASP.NET MVC 2, what is the logic, tips and tricks behind the designed solution. I must say, I like it as Headspring designed it. I just would call this book ASP.NET MVC 2 in Action on CodeCampServer project.

If you want to download and understand the code quite deeply, read this book. The quys around CodeCamperver are really cool ;o)!

If you want to know more about ASP.NET MVC 2 in general than how to use ASP.NET in Alt.NET, way then read this book: Pro ASP.NET MVC 2 Framework, Second Edition (Expert’s Voice in .NET)

IEnumarable with a Count = IEnumerableList

Filed under: .NET, Uncategorized — Frantisek @ 1:07 pm

I do Domain-Drive-Design (DDD) and one of the golder rules practically says that the domain model shouldn’t expose more necessary.

Example:

    1 public class Item

    2 {

    3     public IList<Bid> Bids

    4     {

    5         get; private set; }

    6 

    7     public Item()

    8     {

    9         Bids = new List<Bid>();

   10     }

   11 }

   12 

   13 public class Bid

   14 {

   15 }

The class Item has collection of the Bid(s). So Item can expose property IList Bids {get;}. The problem is that in case Bid has a reference to Item then it’s possible that that Bid1 whose parent item is Item1 is added to Item2. The designer of the domain model enable us to do it. This is violation of the domain model rules.

Solution: we should add method AddBid(Bid bid) {} to the class Item and change the Item’s property Bids to the following IEnumerable Bids {get;}

Fine, but what to do in case there is a logic which would like to know how many bids some item has. IEnumerable doesn’t expose such property. For such cases I create my IEnumerableList.

    1 public interface IEnumerableList<T> : IEnumerable<T>

    2 {

    3     /// <summary>

    4     /// Gets the <see cref="T"/> at the specified index.

    5     /// </summary>

    6     /// <value></value>

    7     T this[int index] { get; }

    8 

    9     /// <summary>

   10     /// Gets the count.

   11     /// </summary>

   12     /// <value>The count.</value>

   13     int Count { get; }

   14 }

and I also created the List implementation called EnumerableList:

    1 public class EnumerableList<T> : IEnumerableList<T>

    2 {

    3     private readonly IList<T> underlyingList;

    4 

    5     /// <summary>

    6     /// Initializes a new instance of the <see cref="EnumerableList&lt;T&gt;"/> class.

    7     /// </summary>

    8     /// <param name="list">The list.</param>

    9     public EnumerableList(IList<T> list)

   10     {

   11         underlyingList = list;

   12     }

   13 

   14     #region Implementation of IEnumerable

   15 

   16     /// <summary>

   17     /// Returns an enumerator that iterates through the collection.

   18     /// </summary>

   19     /// <returns>

   20     /// A <see cref="T:System.Collections.Generic.IEnumerator`1"/> that can be used to iterate through the collection.

   21     /// </returns>

   22     /// <filterpriority>1</filterpriority>

   23     public IEnumerator<T> GetEnumerator()

   24     {

   25         return underlyingList.GetEnumerator();

   26     }

   27 

   28     /// <summary>

   29     /// Returns an enumerator that iterates through a collection.

   30     /// </summary>

   31     /// <returns>

   32     /// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.

   33     /// </returns>

   34     /// <filterpriority>2</filterpriority>

   35     IEnumerator IEnumerable.GetEnumerator()

   36     {

   37         return underlyingList.GetEnumerator();

   38     }

   39 

   40     #endregion

   41 

   42     #region Implementation of IEnumerableList<T>

   43 

   44     /// <summary>

   45     /// Gets the <see cref="T"/> at the specified index.

   46     /// </summary>

   47     /// <value></value>

   48     public T this[int index]

   49     {

   50         get { return underlyingList[index]; }

   51     }

   52 

   53     /// <summary>

   54     /// Gets the count.

   55     /// </summary>

   56     /// <value>The count.</value>

   57     public int Count

   58     {

   59         get { return underlyingList.Count; }

   60     }

   61 

   62     #endregion

   63 }

And the final solution looks like the following:

    1 public class Item

    2    {

    3        public IEnumerableList<Bid> Bids

    4        {

    5            get

    6            {

    7                return new EnumerableList<Bid>(_bids);

    8            }

    9        }

   10        private IList<Bid> _bids;

   11 

   12        public Item()

   13        {

   14            _bids = new List<Bid>();

   15        }

   16 

   17        public void AddBid(Bid bid)

   18        {

   19            _bids.Add(bid);

   20        }

   21    }

   22 

   23    public class Bid

   24    {

   25    }

In this case the domain model doesn’t allow me to do prohibited action.

Original article was published at www.Catarsa.com

Older Posts »

Create a free website or blog at WordPress.com.