Monday, January 29, 2018

State Design Pattern combined with Console.ReadLine

Some times we want console application, when one screen changes other depend on user console read line input

Example:

Start:

user select P:
user select M:
User select P:
User Select F:

It is very easy do with using State design pattern.

Solution:

Classes:

Program.cs:

class Program
{
static void Main(string[] args)
{
IState state = new MainMenuState();
Context context = new Context(state);

while (true)
{
context.Request();
}
}
}

Context.cs:

public sealed class Context
{
public Context(IState state)
{
State = state;
}

public IState State { get; set; }

public void Request()
{
State.PrintOptions();
string userChoise = Console.ReadLine();
State.UpdateState(this, userChoise);
}
}

IState.cs:

public interface IState
    {
        void PrintOptions();
        void UpdateState(Context context, string userChoise);
    }
}

State classes:

public sealed class MainMenuState : IState
{
public void PrintOptions()
{
Console.Clear();
Console.WriteLine("Hello. Is Main menu");
Console.WriteLine("P - print hello");
}

public void UpdateState(Context context, string userChoise)
{
switch (userChoise)
{
case "P":
context.State = new PrintHelloState();
break;
}
}
}

public class PrintHelloState : IState
{
public void PrintOptions()
{
Console.Clear();
Console.WriteLine("Hello my little friend!");
Console.WriteLine("M - main menu");
Console.WriteLine("F - finish menu");
}

public void UpdateState(Context context, string userChoise)
{
switch (userChoise)
{
case "M":
context.State = new MainMenuState();
break;
case "F":
context.State = new FinishMenuState();
break;
}
}
}

public sealed class FinishMenuState : IState
{
public void PrintOptions()
{
Console.Clear();
Console.WriteLine("Bye Bye");
Thread.Sleep(1000);
Console.WriteLine("See you");
Thread.Sleep(1000);
Environment.Exit(0);
}

public void UpdateState(Context context, string userChoise)
{

}
}

Also, some functionality can be added in one of overloaded function, or added new one.

 

Wednesday, January 24, 2018

Multi threading initially supporting in Domain Object and Business Logic

In previous post i was make superficial review on DO and BL

DO should not, generally, support Multi threading initially.

BL should support initialy Multi threading in next case: static methods or static members

In case of static member always should support multi threading. It is shared entity by a-priory
In case of static method, if this method uses static member (which was described earlier) so it also should support multi threading.  If static method not uses any static members, it is should not support multi threading initially

Initially - i mean without considering customer. If customer wish DO supports multi threading -  this is the customers's concern.

Partitioning of application into main modules

Application should be partitioning to main modules.

For example, i will consider train system.
It is consists from: Train, routes, stations, search train, add route, rich WPF UI, console UI, user click some button to get stations etc.

DO - domain object. It is anemic entity, consists only Train, Route, Station
BL - business logic. It is operations on DO: search route, serialization/deserialization of DO objects etc.
UI - is how all this looks like on screen. Can be made by WPF, WinForms, Console etc.

How knows who?

DO do not know anyone.
BL knows DO only.
UI knows both BL and DO.

Its very superficial review, but it is very important to understand this concept

Tuesday, August 8, 2017

Dependency Injector NINJECT full example

Here is example of library, using Ninject and also test

Library:

using Ninject;
using Ninject.Modules;

namespace NinjectExample
{
    #region Interface
    public interface IProduct
    {
        string InsertProduct();
    }
    #endregion

    #region Interface implementation
    public class ConcreteProduct1 : IProduct
    {
        public string InsertProduct()
        {
            string value = "Dependency 1 injection using Ninject";
            return value;
        }
    }

    public class ConcreteProduct2 : IProduct
    {
        public string InsertProduct()
        {
            string value = "Dependency 2 injection using Ninject";
            return value;
        }
    }
    #endregion

    #region Dependency Injector
    internal class ProductsBinder : NinjectModule
    {
        private string _productName;

        public ProductsBinder(string productName)
        {
            _productName = productName;
        }

        public override void Load()
        {
            switch (_productName)
            {
                case "DataAccessLayer1":
                    Bind<IProduct>().To<ConcreteProduct1>();
                    break;
                case "DataAccessLayer2":
                    Bind<IProduct>().To<ConcreteProduct2>();
                    break;
            }
        }
    }
    #endregion

    #region Factory
    public class FactoryProduct
    {
        public static IProduct Create(string name)
        {
            IKernel krn = new StandardKernel(new ProductsBinder(name));
            return krn.Get<IProduct>();
        }
    }
    #endregion
}

Test:

using Microsoft.VisualStudio.TestTools.UnitTesting;
using NinjectExample;

namespace UnitTestProject1
{
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void TestMethod1()
        {
            IProduct dl = FactoryProduct.Create("DataAccessLayer1");
            Assert.AreEqual("Dependency 1 injection using Ninject", dl.InsertProduct());
        }

        [TestMethod]
        public void TestMethod2()
        {
            IProduct dl = FactoryProduct.Create("DataAccessLayer2");
            Assert.AreEqual("Dependency 2 injection using Ninject", dl.InsertProduct());
        }
    }
}

Of course, all tests passed. 

Monday, August 7, 2017

Dependency Injector NINJECT

Hello
Stuff, i learned recently

For example, there is peace of code:

public partial class MainWindow : Window
{
ISubject _subject;

public MainWindow()
{
_subject = new WeatherData();
}

.... other code....
}


What is a problem with this code?
a couple of.
1. MainWindow should to know about ISubject realization. So, it violate OCP. Class MainWindow do some job and it also instantiate _subject by concrete realization.

2.  If i will want other _subject realization, i will open MainWindow and do changes. It is violates OCP.

3. It is not using Ninject dependency injector ;-)

So, how we fix it?

1. In Visual studio package manager console type :
PM> install-package Ninject

2. Create class, which bind interface and realization by using Ninject:
public class SubjectModule : NinjectModule
{
public override void Load()
{
Bind<ISubject>().To<WeatherData>();
}
}

what is mean, is realization of ISubject is WeatherData

3. Lets create some factory, which use SubjectModule :
public class SubjectFactory
{
public static ISubject Create()
{
IKernel krnl = new StandardKernel(new SubjectModule());
return krnl.Get<ISubject>();
}
}

4. lets do refactoring to MainWindow :
public partial class MainWindow : Window
{
ISubject _subject;

public MainWindow()
{
_subject = SubjectFactory.Create();
}
.... other code....
}

that all!
Now we can change Binding and get other realization inside of MainWindow  without change its code! And, from now, MainWindow  should not know anything about _subject concrete realization

Enjoy

P.S. thanks to Vova about make me to learn it

x

Thursday, June 22, 2017

.NET DocumentViewer FindToolBar customization

Hi
If you using MS .NET DocumentViewer and you want customize Find field

there some ways.
In my example i can change text "Type text to find..." to other one ("Find me!") and also disable alefHamza field

ContentControl findToolBar = documentViewer.Template.FindName("PART_FindToolBarHost", documentViewer) as ContentControl;
if (findToolBar == null) return;

Type baseType = findToolBar.Content.GetType();
MemberInfo[] dynMethod = baseType.GetMember("OptionsMenuItem", BindingFlags.NonPublic | BindingFlags.Instance);
FieldInfo alefHamzaField = (dynMethod[0] as FieldInfo);
System.Windows.Controls.MenuItem menuItem = alefHamzaField.GetValue(findToolBar.Content) as System.Windows.Controls.MenuItem;
menuItem.Visibility = System.Windows.Visibility.Collapsed;

dynMethod = baseType.GetMember("FindTextLabel", BindingFlags.NonPublic | BindingFlags.Instance);
FieldInfo findTextLabel = (dynMethod[0] as FieldInfo);
System.Windows.Controls.Label lbl = findTextLabel.GetValue(findToolBar.Content) as System.Windows.Controls.Label;
lbl.Content = "Find me!"

Thanks for watching!

Wednesday, December 31, 2014

Command design pattern. Simple version.

Hello
We have Light devices, which can beam or not.
We do not want control directly Light source, because we want learn Command Design Pattern :-)
Of course, the reasons is others. For example, we want to be less sensitive to changes.

In implementation of Command Design Patter in our example we have 3 players:

  • Device: is a Light which can be "ON" or "OFF" state.
  • Command turn "ON" the lights: is Light "ON" command. Is a class, which wraps above Light. Heart of this class - turn "ON" the Light, which encapsulated in single function "Execute". 
  • Remote: some class which got command and call it "Execute". When user call "Click Remote" of this class, its method call "Execute" of command
Illustration:




Code behind it:
public interface ICommand
{
    void Execute();
}

public class Light
{
    public void On()
    {
        Console.WriteLine("Light is ON");
    }

    public void Off()
    {
        Console.WriteLine("Light is OFF");
    }
}

public class LightOnCommand : ICommand
{
    private Light _light;

    public LightOnCommand(Light light)
    {
        _light = light;
    }

    public void Execute()
    {
        _light.On();
    }
}

public class SimpleRemoteControl
{
    ICommand _command;

    public void SetCommand(ICommand command)
    {
        _command = command;
    }

    public void ClickButton()
    {
        _command.Execute();
    }
}

Tester:
Light light = new Light();
ICommand lightOnCmd = new LightOnCommand(light);

SimpleRemoteControl remote = new SimpleRemoteControl();
remote.SetCommand(lightOnCmd);
remote.ClickButton();

Result: