Friday, August 8, 2014

Covariant and Contravariant

Note that these constraints can be overridden by code, extension method to convert anything to anything

    class Program
    {
        static void Main(string[] args)
        {
            IW<String> iwStr = new W<string>("Test");
            IW<object> iwObj =  iwStr.ToObject2();
        } 
    }

    public interface IW<T>
    {
        T W { get;  }
    }

    public class W<T> : IW<T>
    {
        T _w;
        public W(T w)
        {
            _w = w;
        }
        T IW<T>.W
        {
            get { return _w; }
        }
    }

    public static  class Ext
    {
        public static IW<object> ToObject2(this IW<string> iw)
        {
            return new W<object>(iw.W);
        }
    }

Thursday, August 7, 2014

Notes on Expression Blend

1. Gradient can used on Background and Opacity Mask. the latter could be on an Image

2. Control States are model by Visual State Group (Common, Focused) and a grid can have Opacity set for two group if not conflict
    These states are visible only Edit Template --> Edit Copy for a control.

3. Two workspace under windows: Design and Animation. The 1st relates to animation by Assets-> Control  StoryBoard action and 
set event trigger  and StoryBoard1.

4. Animation workSpace can utilize Transform Property and specifically Layout Transform to do Rotation. It may need to first turn off 
recording for StoryBoard to set key frame at 0 sec, then recording on to drag to sec to rotate 360 and restore size back.

5. Any group of Path, Drawing, Image, Controls can be Object/Timeline -->select multiple--> right click->Control->make User Control.
Its code behind can define a public prop showing up in Properties Grid Misc when it is hosted in a MainWindow.xaml.

6. Shape Set Operation and arbitrary path generation: any two shape can object->Combine -->(Unit, Substract, Intersect), including 
TextBlock where text can be substracted.  Also can convert Shape to path by Object->Path-->Convert to path. 

7. Carry User Control around: User Control build in Control Library Project can be used in WPF project seen under Assets Tab. 
Need to add project references. This also works even for any project type but have to manually add/remove when UC changes. Also add existing
 item as UC but that is just a copy of Xaml and cs and new changes will not automatically moved.

8. Easing Function: must select a Key Frame for property visible, in Animation Workspace. KeySpline =Simple cubic,Hold-in=no interpolation,
 direct to the end. 

9. Layout Controls: Grid's ScrollbarVisibility Property checkbox are attached property ScrollViewer.* and
 does not work well. So directly set it on ScrollViewer if you can; DockPanel LastChildFill also attached
 property and override the last child dock.

10. Layout Controls has Canvas and Grid, Grid has two mode: Grid Model and Canvas mode. the latter mode is not Canvas but behave 
like one --- child control are absolutely positioned not responding to Grid resizing.

11. Layout controls Border is very different: it has Border Brush, Back Ground, Corner Radius. But it can only hold one child.
 To host more children need to Object->Group into --> Grid to add grid and drag on more child.

Monday, July 28, 2014

VS.Net Environment Configuration "Add-in" -- now called VS Package

(1) Install VS 2010 SP1 SDK
(2) Tool -- Extension Manager, search VSPackage, install VSPackage Template and VSPackage Builder template
(3) New Project, the Builder, Drag on "Add Toolbar" from toolbox, add two Combo, one button. Connect them to Group1.

Now all will show up in Toolbar.

Code to get Configuration Data from Server Http Endpoint--- must write in a seperate class file or Builder will overwrite it.

    class Configurator
    {
        public static string StartProjectName { get; private set; }
        public static void SetStartArguments(EnvDTE.DTE dte,string currEnvCombo, string currVerCombo)
        {
            foreach (Project p in dte.Solution.Projects)
            {
                if (p.Name == StartProjectName)
                p.ConfigurationManager.ActiveConfiguration.Properties.Item("StartArguments").Value = "env="+currEnvCombo+"\r\nver="+currVerCombo+"\r\nwebdata="+data;
            }
        }

        static string data = "";
        public static void ReadConfigurationFromServer(ref string[] envArray, ref string[] verArray)
        {
            // Get Configuration from Server for all (env ver) and set two combo, start project etc.
            WebClient wc = new WebClient();
            data = wc.DownloadString("http://www.cnn.com").Substring(300, 10);
            StartProjectName = "WpfApplication1";
            envArray=new string[]{"UAT","LIVE","Local"};
            verArray=new string[]{"Trading (London)","Trading (NYC)","Sales"};
        }
    }

        public VSPackage1PackageBase()
        {
            Configurator.ReadConfigurationFromServer(ref envComboChoices, ref verComboChoices);
        }

        protected virtual void envComboExecuteHandler(object sender, EventArgs e)
        { ...
        Configurator.SetStartArguments(GetService(typeof(DTE)) as DTE, currentenvComboChoice, currentverComboChoice);

Deployment: VSPackage project auto generate .vsix file for installation. But Do check vsixmanifest file "Select Editions" to include all VS.net 2010 editions

Thursday, July 24, 2014

Practical MVVM/RX WPF App


Building MVVM/Rx WPF need to glue together multiple interface and correctly hand off to Dispatcher:

(1) (engineering) Need to use nuget.config align with .sln so package managed at solution level 
          <add key="repositorypath" value="Packages" />

(2) (design pattern) View - ViewModel --VMController--Adapter -- Transport

(3) (engineering) Fluent API can easily glue DataContext to VM, VMController point to VM

    public class FluentFactory
    {
        public FluentFactory ViewModelController(Func<IViewModelController> viewModelControllerFactory)
        {
            var f = viewModelControllerFactory.Invoke();
            f.ViewModel = _viewModel;
            return this;
        }

        INotifyPropertyChanged _viewModel=null;
        public FluentFactory ViewModel(Func<INotifyPropertyChanged> viewModelFactory)
        {
            _viewModel = viewModelFactory.Invoke();
            return this;
        }

        public void View(Func<FrameworkElement> viewFactory)
        {
            FrameworkElement fe = viewFactory.Invoke();
            fe.DataContext = _viewModel;
        }
    }

(4) (MVVM) Module can resolve instance to inject into DockingViewManager
    public class TradingModule : IModule
    {
        IUnityContainer _container;
        public TradingModule(IUnityContainer container)
        {
            _container = container;
        }
        public void Initialize()
        {
            _container.RegisterInstance<ITransport>(new TradingTransport());
            _container.RegisterInstance<IAdapter>(new TradingAdapter());
            _container.RegisterInstance<IScheduler>(new NewThreadScheduler());
            _container.RegisterInstance<LocalScheduler>(DispatcherScheduler.Current);
        }
    }

(5) (Rx) DockingViewManager will Create VMController when Button Click ask for well known view and then start Observable sequence

    public class DockingViewManager : IDockingViewManager
    {
        public DockingViewManager(ITransport transport, IAdapter adapter, IScheduler scheduler, LocalScheduler dispatcher)

        public UserControl GetDockingView(WellknowViewName viewName)
        {
            FluentFactory f = new FluentFactory();
            if (viewName == WellknowViewName.DurationTraderView)
            {
                DurationTraderView durView = new DurationTraderView();

                f.ViewModel(() => new DurationTraderViewModel())
                .ViewModelController(() => CreateDurationTraderViewModelController())
                .View(() => durView);
                return durView;
            }

            if (viewName == WellknowViewName._5_10Yr)
            {
                _5_10YRView view = new _5_10YRView();

                f.ViewModel(() => new _5_10YRViewModel())
                .ViewModelController(() => Create_5_10YRViewModelController())
                .View(() => view);
                return view;
            }
            return new UserControl();
        }

        public DurationTraderViewModelController CreateDurationTraderViewModelController()
        {
            return new DurationTraderViewModelController(_transport,_adapter,_scheduler,_dispatcher);
        }
    }


    public class DurationTraderViewModelController : IViewModelController
    {
        public INotifyPropertyChanged ViewModel { get; set; }

        public DurationTraderViewModelController(ITransport transport, IAdapter adapter, IScheduler scheduler, LocalScheduler dispatcher)
        {
            transport.GetTradingObservables()
                .SubscribeOn(scheduler)
                .ObserveOn(dispatcher)
                .Subscribe(fSet => adapter.updater(fSet, ViewModel));
        }
    }

    public class TradingTransport : ITransport
    {
        public IObservable<IFieldDataSet> GetTradingObservables()
        {
            return Observable.Create<IFieldDataSet>((obsr) =>
            {
                return Observable.Timer(TimeSpan.Zero, TimeSpan.FromSeconds(1)).Select(i => new FieldDataSet()).Subscribe(obsr);
            });
        }
    }

Side Note--- OnPropertyChange("Cusip") is error prone with Hard-coded string. Better utilize Expression tree in C# 4.0
     
        SetProperty(ref _cusip, value,()=>Cusip);

        public void SetProperty<T>(ref T field, T value, Expression<Func<T>> exp)
        {
            if (EqualityComparer<T>.Default.Equals(field, value)) return;
            field = value;
            if (PropertyChanged != null)
            {
                MemberExpression me = exp.Body as MemberExpression;
                if (me != null && me.Member != null)
                    PropertyChanged(this, new PropertyChangedEventArgs(me.Member.Name));
            }
        }

Side Note --- Load Module by Config
  <modules>
    <module assemblyFile="Modules.dll" 
            moduleType="Modules.TradingModule, Modules, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
            moduleName="TradingModule" startupLoaded="true" />
  </modules>

    public class DemoUnityBootstrapper : UnityBootstrapper
    {
        protected override IModuleCatalog CreateModuleCatalog()
        {
            return new ConfigurationModuleCatalog();
        }
    }

Sunday, July 6, 2014

Producer Consumer Pattern with HandOff point

// Both Data Queue and Queue under SynchronizationContext allow handoff of data
// Data Consumer can be parallel Enumerable or Subscribe to Observables
// UI can only singled threaded Async or sync

        void BlockingCollectionAsQueue()
        {
            BlockingCollection<string> ServerData = new BlockingCollection<string>(10000);
            ServerData.Add("Data");
            ServerData.CompleteAdding();
            string data1;
            ServerData.TryTake(out data1, TimeSpan.FromMilliseconds(2));
            IEnumerable<string> data = ServerData.GetConsumingEnumerable();
            foreach (var v in data.AsParallel().AsOrdered().Select(l => Regex.Replace(l, @"\s+", ""))) ;
        }

        void UIMarshalling()
        {
            ThreadPool.QueueUserWorkItem((s) =>
            {
                //do some server side work
                // UIControl.Invoke();
                //Dispatcher.Invoke();
                SendOrPostCallback spcb = new SendOrPostCallback((obj) => { });
                // SynchronizationContext =WPF.Dispatcher or WF.Control.Invoke
                SynchronizationContext.Current.Send((state) =>
                {
                    //UI.Property="";
                }, "");
            });
        }
http://www.martinpersson.org/wordpress/2012/12/application-launcher/

TPL Fork Join code Pattern

// Count down until all 4 are signaled
     CountdownEvent ce = new CountdownEvent(4);
            ce.Signal();
            ce.Wait();

// count up by add one for each work
     ce = new CountdownEvent(1);
     ce.AddCount(1);
     ce.Signal();
     ce.Wait();

// Inlining -- Recursive Decomposition
 // walk by directly parallel
        void Walk2<T>(Tree<T> root, Action<T> action)
        {
            if (root == null) return;
            Parallel.Invoke(
                ()=> action(root.Data),
                () => Walk2(root.Left, action),
                () => Walk2(root.Right, action));
        }

//Continuation Chaining
// Parallel <> Sum of Tasks, Unwrap() map Task<Task> to Task for Completion.
            if (root == null) return _CompletedTask;
            Task<Task> t2 = Task.Factory.StartNew(() => Walk(root.Left, action));
            Task<Task> t3 = Task.Factory.StartNew(() => Walk(root.Right, action));
            return Task.Factory.ContinueWhenAll(new Task[] { t1, t2.Unwrap(), t3.Unwrap() },
             task => Task.WaitAll(task));
public static Task _CompletedTask = ((Func<Task>)(() =>
        {
            TaskCompletionSource<object> ts = new TaskCompletionSource<object>();
            ts.SetResult(null);
            return ts.Task;
        }))();

//Parallel with options:
// option can cacell, set schedule, MaxDegree.
// Parallel.For can be stoped by loop.Stop() inside For
Parallel.Invoke(opts, () => { }, () => { }, () => { });
            CancellationTokenSource ts = new CancellationTokenSource();
            
            ParallelOptions opts = new ParallelOptions()
            {
                MaxDegreeOfParallelism = 2,
                TaskScheduler = TaskScheduler.FromCurrentSynchronizationContext(),
                CancellationToken = ts.Token
            };

 ParallelLoopResult res = Parallel.For(0, 10000, () => 1, (j, loop, sub) =>
            {
                if (loop.ShouldExitCurrentIteration) return 0;
                loop.Stop();

Testing Observables using NUnit/Moq in MVVM

Mock->setup a function must run for each parameter change.
Obs.Create take in IObser and return IDispoable. So next a Subject to call OnNext.
Note that Subject.sub(Obr) will allow OnNext to stream out Obs.
Finally, testSchedule must advance to see data coming out.

Mock _mockT= Mock;
_VMController = new(_mockT.Object, ...);
[Test] public void IdChanged() {
   Id = new Hashset(){guid};
   _mockT.Setup(p=>ObserveData(Id)
   .Return(GenerateObs(id:Id, data: 100.01));
   Assert.AreEqual(_VMController.ViewModel.DataCollecton.Count,1);
}
IObs<PT> GenerateObs(string id="", double? data=null,DateTime logicalDate=null) {
Data data = new (...);
return Observable.Create(obsr=>{   // Func<IObserver,IDispoable>
var s = new Subject<Data>();
   s.subscribe(obsr);
   onNext<Data>(s,data);
return s;
});
}
void onNext<T> (IObserver obr, T data)
{
  obr.OnNext(data);
  _testSchedule.AdvancedBy(250ms);
}