IgorShare Thoughts and Ideas

Consulting and Training

Archive for January, 2008

Dynamically Composing Expression Predicates

Posted by Igor Moochnick on 01/31/2008

Do not miss a great article about the internals of building dynamic LINQ queries – Dynamically Composing Expression Predicates.

I’ve still not quite bought the idea of LINQ. It’s compact, descriptive and strongly timed – all great, but … Actually I’d like to say: BUT! This “but” is a big question mark for the LINQ’s feasibility. It’s not flexible enough for our day-to-day tasks. It’s as hard-coded as “foreach” contract. More descriptive and nice looking, but still a very fancy “foreach” loop.

I think Dynamic LINQ is about to change my perspective on LINQ, but, while it gives more flexibility, it breaks the nice and fit LINQ constructs and brings us back to SQL-like queries where we have no strong types and no compiler-time check. Bottom line – back to square one.

I think we need either another .NET compiler revision to support dynamic LINQ (where it’ll allow us to emit LINQ queries from strings) or a some kind of LINQ Dom in-memory compiler library. I’m, actually, leaning towards the lateral (see my post CodeDom extensions and dynamic LINQ (string/script to LINQ emitting)).

Posted in LINQ, Thoughts | Leave a Comment »

Workflow ActivityDesigner should notify everyone if it changes an activity property

Posted by Igor Moochnick on 01/29/2008

If your Activity Designer makes any property change on an activity it attached to, it should broadcast a notification to every activity in the workflow so the other activities can react to such a change if they need to. It is possible to acheive via a TypeDescriptor or, in more generic case, via the IComponentChangeService.

This is how you can do it in a quick way:

TypeDescriptor.GetProperties(parentActivity).Find(propertyName, false).SetValue(parentActivity, newValue);

And this is more generic approach:

private void NotifyActivityChange(Activity activity, string propertyName, object newValue)
{
    IComponentChangeService svc = (IComponentChangeService)this.GetService(typeof(IComponentChangeService));
    PropertyDescriptor propDescr = TypeDescriptor.GetProperties(activity).Find(propertyName, false);
    svc.OnComponentChanging(activity, propDescr);
    object oldValue = propDescr.GetValue(activity);
    propDescr.SetValue(activity, newValue);
    svc.OnComponentChanged(parentActivity, propDescr, oldValue, newValue);
}

[Thanks to MSDN Workflow Foundation Forum and to Matt Milner in particular]

Posted in C#, Tutorials, Workflows | Leave a Comment »

Minimal set of steps to connect to Oracle DB

Posted by Igor Moochnick on 01/28/2008

clip_image001

This is what you need to do on your deployment server to make sure your app can access Oracle:

  1. Get the Oracle ODAC. Make sure that you’re using the appropriate version. In most of the cases ODAC versions are backward compatible, so you can use ODAC from 10g to connect to 9i, but you’ll have problem in some cases to connect to 11g. I, personally, prefer to use the most recent and most distributed/polished version. So today I use 10g since 11g is not that thoroughly polished.
  2. Install just the ODAC Components – see it on the picture. Do not install DB Extensions if you really need them.
  3. Make sure to change your connection string appropriately.

Personally, I prefer not to use the TNSNames.ora file to store my connection info, mainly because I have a heterogeneous environment where some of my services are connecting to MS SQL and some of them to Oracle. This allows me to control all the connection definition in the consistent manner, so this is, for example, how you connection string to Oracle may look like:

   1: <connectionStrings>
   2:   <add name="ConnectionString"
   3:         connectionString="Data Source=(DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)
   4:             (HOST = your_oracle_host)(PORT = 1521))) (CONNECT_DATA = (SID = db_sid) (SERVER = DEDICATED)));
   5:             pooling=true;connection lifetime=300;enlist=true;min pool size=1;max pool size=100;persist security info=true;"
   6:         providerName="System.Data.OracleClient" />
   7: </connectionStrings>

 

Note that the connection looks almost identical (including the connection pooling) to the SQL one except from the following things:

  1. providerName – makes sure the ADO will use Oracle ODAC
  2. DataSource – to make it simple, just copy your connection info from TNSNames.ora directly into your connection string (AS-IS). You can use any Oracle dev tool to create such connection definition.
  3. A bunch of connection string parameters are not working in Oracle connection (it’ll throw an Exception when you’ll create a DB connection) – refer to documentation for more info.

Stay tuned for more info on how to write your code to be DB agnostic. It’s pretty tricky and not straightforward as it described in the DbProvider-related documentation mainly due to vast differences between MS SQL and Oracle implementations.

Posted in DB, Tutorials | Leave a Comment »

How to find all Workflows in an assembly

Posted by Igor Moochnick on 01/28/2008

This is a beginning of series of articles on workflows discoverablity and automation.

It’s easy to start a workflow if you know it’s type:

   1: WorkflowRuntime runtime = new WorkflowRuntime();
   2: runtime.StartRuntime();
   3: 
   4: WorkflowInstance workflow = runtime.CreateWorkflow(typeof(MyWorkflowType), parms);

But what if you have an assembly and you don’t know a workflow type? Reflection is the answer. This is how you can find all the types in an assembly that inherit from an Activity (base type for all workflows) type:

   1: public static IEnumerable<Type> FindWorkflows(Assembly asm)
   2: {
   3:     return from t in asm.GetTypes()
   4:            where t.IsSubclassOf(typeof(Activity))
   5:            select t;
   6: }
   7: 
   8: [TestMethod]
   9: public void FindAllWorkflowsInAssembly()
  10: {
  11:     foreach (Type t in WFHelper.FindWorkflows(WFHelper.LoadWorkflowAssembly(assembly_path)))
  12:     {
  13:         System.Diagnostics.Trace.WriteLine(t.Name);
  14:     }
  15: }

Note: the list, returned by FindWorfklows function, will contain all Custom activities in the provided assembly as well.

If you want to know how to narrow down the list, stay tuned.

Posted in C#, Reflection, Tutorials, Workflows | Leave a Comment »

Did you know: using ToLower on a Unicode text can cause a security problem?

Posted by Igor Moochnick on 01/26/2008

Recently watched the latest DnrTV show #97 (love them!) with Kathleen Dollard (check her blog Leaning Into Windows). Great show! Kathleen went through a lot of things that are rarely used in the day-to-day projects but, if overlooked, can cause a serious problem and put the whole project/product at risk. Here are 2 that are really worth remembering:

1. In a product that works with Unicode strings (Localized) and do a lot of string comparisons, it’s better to use ToUpper than ToLower. ToUpper will not work correctly for a couple of languages, but ToLower, not only fail for more languages, but, also, can expose a bunch of security problems within Unicode implementation.

2. Do not write ANY code that changes variables in a partial method call. If a partial method implementation will be removed – such code will be removed as well and will cause an unpredictable result. To understand this check out the following code snippet:

   1: partial void PrintNum(int n);
   2:  
   3: public int AddWithIncrement(int a, int b)
   4: {
   5:    PrintNum(a++);
   6:    return a+b;
   7: }

 

Let’s say that a=1 and b=2. If the PrintNum method will have a declaration, then the AddWithIncrement function will return 4. On the other hand, if the declaration of PrintNum will be removed, the compiler will remove (ignore) the whole line #5 (PrintNum(a++)), hence the a++ will not be executed and AddWithIncrement function will return 3.

So, be careful, you have been warned!

Posted in C#, Software, Thoughts, Tutorials, Visual Studio | Leave a Comment »

Reflections on the Microsoft WPF Certification BETA Exam (70-502)

Posted by Igor Moochnick on 01/25/2008

Click to get the running application

[ Update: just got a word that I’ve passed the test. Good luck to those who plan to take the test. ]

Today I’ve tried Microsoft’s WPF Certification BETA exam. The exam is still rough: a lot of confusing questions, a bunch of questions with more than one correct answer and a bunch with no correct answer at all. At the end of the exam I was asked to provide my comments and I was happy to, but … I was timed on this portion as well !!! They give you a very limited time to review all the questions again in a very short time. The same amount of questions that took me 2 hours to complete. This was the most bizarre experience ever – they ask for our opinion and do not want to listen to you. How do you like that?!!

If you want to be prepared for the exam, try to replicate my result on the left. It’ll give you a great deal of experience and will cover about 50% of the needed skills. If you’ll make sure that you can retrieve all the presented information from an external source as well as let a user to select a single item from a collection – this will cover the biggest remainder of the needed skills.

Make sure to check the preparation guide for exam 70-502 for a detailed list of skills.

For the lazy ones I provide the XAML code and the running app. I do not claim that this is the most beautiful solution, but it’s the most elegant and short one I’ve came up with.

<?xml version="1.0" encoding="utf-8"?>
<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:d="http://schemas.microsoft.com/expression/blend/2006" mc:Ignorable="d"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" x:Class="MarilynSite.Page1" x:Name="Page"
  WindowTitle="Page"
  FlowDirection="LeftToRight"
  Width="Auto" Height="Auto"
  WindowWidth="740" WindowHeight="680">
  
  <Page.Resources>
    <Canvas x:Key="BookWithReflection" Width="138" HorizontalAlignment="Left">
      <Canvas x:Name="MainSource">
        <Border BorderThickness="2,2,2,2" CornerRadius="4,4,4,4" Width="137.702" Height="184">
          <Border.BorderBrush>
            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
              <GradientStop Color="#FFFAAA00" Offset="0"/>
              <GradientStop Color="#FFFFFFFF" Offset="1"/>
            </LinearGradientBrush>
          </Border.BorderBrush>
          <Image Source="http://marilyn-armstrong.com/yahoo_site_admin/assets/images/FromTheBridge.35063808_std.gif" Width="138.702" Height="205" />
        </Border>
        <Label Content="The 12-foot Teepee" FontWeight="Bold" Foreground="#FFFFFFFF" FontSize="12" Canvas.Top="33" Canvas.Left="5" RenderTransformOrigin="0.5,0.5">
          <Label.RenderTransform>
            <TransformGroup>
              <ScaleTransform ScaleX="1" ScaleY="2.5"/>
              <SkewTransform AngleX="0" AngleY="0"/>
              <RotateTransform Angle="0"/>
              <TranslateTransform X="0" Y="0"/>
            </TransformGroup>
          </Label.RenderTransform>
        </Label>
        <Label Content="Merilyn Armstrong" FontWeight="Bold" Canvas.Top="83" Canvas.Left="8">
          <Label.Foreground>
            <LinearGradientBrush EndPoint="0.886,0.516" StartPoint="0.071,0.516">
              <GradientStop Color="#FF000000" Offset="0"/>
              <GradientStop Color="#FFFFFFFF" Offset="1"/>
            </LinearGradientBrush>
          </Label.Foreground>
        </Label>
      </Canvas>
      <Rectangle Height="100" Width="136" HorizontalAlignment="Left" VerticalAlignment="Bottom" RenderTransformOrigin="0.5,0.5" d:LayoutOverrides="VerticalAlignment" Canvas.Top="171">
        <Rectangle.RenderTransform>
          <TransformGroup>
            <ScaleTransform ScaleX="1" ScaleY="-1"/>
            <SkewTransform AngleX="0" AngleY="0"/>
            <RotateTransform Angle="0"/>
            <TranslateTransform X="0" Y="30"/>
          </TransformGroup>
        </Rectangle.RenderTransform>
        <Rectangle.OpacityMask>
          <LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
            <GradientStop Color="Transparent" Offset="0"/>
            <GradientStop Color="#99666666" Offset="1"/>
          </LinearGradientBrush>
        </Rectangle.OpacityMask>
        <Rectangle.Fill>
          <VisualBrush Visual="{Binding ElementName=MainSource}" />
        </Rectangle.Fill>
      </Rectangle>
    </Canvas>
    <Storyboard x:Key="RockCover" RepeatBehavior="Forever" AutoReverse="True">
      <Rotation3DAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="geometryModel3D" Storyboard.TargetProperty="(Model3D.Transform).(Transform3DGroup.Children)&#91;2&#93;.(RotateTransform3D.Rotation)">
        <SplineRotation3DKeyFrame KeyTime="00:00:00">
          <SplineRotation3DKeyFrame.Value>
            <AxisAngleRotation3D Angle="20" Axis="0,1,0"/>
          </SplineRotation3DKeyFrame.Value>
        </SplineRotation3DKeyFrame>
        <SplineRotation3DKeyFrame KeyTime="00:00:05">
          <SplineRotation3DKeyFrame.Value>
            <AxisAngleRotation3D Angle="20" Axis="0,-1,0"/>
          </SplineRotation3DKeyFrame.Value>
        </SplineRotation3DKeyFrame>
      </Rotation3DAnimationUsingKeyFrames>
    </Storyboard>
  </Page.Resources>
  
  <Page.Triggers>
    <EventTrigger RoutedEvent="FrameworkElement.Loaded">
      <BeginStoryboard Storyboard="{StaticResource RockCover}"/>
    </EventTrigger>
    <EventTrigger RoutedEvent="FrameworkElement.Loaded">
      <BeginStoryboard Storyboard="{StaticResource RockCover}"/>
    </EventTrigger>
  </Page.Triggers>

  <Page.Background>
    <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
      <GradientStop Color="#FF000000" Offset="0"/>
      <GradientStop Color="#FF7C7C7C" Offset="1"/>
      <GradientStop Color="#FF4D4D4D" Offset="0.586"/>
      <GradientStop Color="#FF959595" Offset="0.538"/>
    </LinearGradientBrush>
  </Page.Background>

  <Grid x:Name="LayoutRoot">
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="0.4*"/>
      <ColumnDefinition Width="0.6*"/>
    </Grid.ColumnDefinitions>
    <Viewport3D Margin="8,29,0,28" RenderTransformOrigin="0.5,0.5" Width="270" HorizontalAlignment="Left" Grid.Column="0">
      <Viewport3D.RenderTransform>
        <TransformGroup>
          <ScaleTransform ScaleX="1" ScaleY="1"/>
          <SkewTransform AngleX="0" AngleY="0"/>
          <RotateTransform Angle="0"/>
          <TranslateTransform X="0" Y="0"/>
        </TransformGroup>
      </Viewport3D.RenderTransform>
      <Viewport3D.Camera>
        <PerspectiveCamera FieldOfView="45" FarPlaneDistance="100" LookDirection="0,0,-4" NearPlaneDistance="0.1" Position="0,0,3.4142135623731" UpDirection="0,1,0"/>
      </Viewport3D.Camera>
      <Viewport3D.Children>
        <ModelVisual3D x:Name="LightSource">
          <ModelVisual3D.Content>
            <AmbientLight />
          </ModelVisual3D.Content>
        </ModelVisual3D>
        <ModelVisual3D>
          <ModelVisual3D.Content>
            <GeometryModel3D x:Name="geometryModel3D">
              <GeometryModel3D.Transform>
                <Transform3DGroup>
                  <TranslateTransform3D OffsetX="0" OffsetY="0" OffsetZ="0"/>
                  <ScaleTransform3D ScaleX="1" ScaleY="1" ScaleZ="1"/>
                  <RotateTransform3D d:EulerAngles="0,0,0"/>
                  <TranslateTransform3D OffsetX="0" OffsetY="0" OffsetZ="0"/>
                  <TranslateTransform3D OffsetX="0" OffsetY="0" OffsetZ="0"/>
                </Transform3DGroup>
              </GeometryModel3D.Transform>
              <GeometryModel3D.Material>
                <DiffuseMaterial>
                  <DiffuseMaterial.Brush>
                    <VisualBrush Visual="{StaticResource BookWithReflection}" ViewboxUnits="RelativeToBoundingBox" />
                  </DiffuseMaterial.Brush>
                </DiffuseMaterial>
              </GeometryModel3D.Material>
              <GeometryModel3D.Geometry>
                <MeshGeometry3D Positions="-.9,-2,0 .9,-2,0, .9,2,0 -.9,2,0" TriangleIndices="0 1 2, 0 2 3" TextureCoordinates="0,1 1,1 1,0 0,0" />
              </GeometryModel3D.Geometry>
            </GeometryModel3D>
          </ModelVisual3D.Content>
        </ModelVisual3D>
      </Viewport3D.Children>
    </Viewport3D>
    
    <Grid Margin="8,8,8,8" Grid.Column="1" Background="#FFCCCCCC">
      <FlowDocumentReader>
        <FlowDocument ColumnWidth="300" IsOptimalParagraphEnabled="True" IsHyphenationEnabled="True">
          <Section FontSize="16" Foreground="Black">
            <Paragraph>
              <Figure Width="180" Background="Silver"
              HorizontalAnchor="PageLeft"
              HorizontalOffset="0" VerticalOffset="40">
                <Paragraph IsHyphenationEnabled="True" FontSize="12"
                FontStyle="Italic" TextAlignment="Left">
                  "Nevertheless, Armstrong’s distinctive pathos in the way her narrative flowingly handles an unredeemable childhood with an adulthood filled with love and longing but continued financial and health-related chaos is indeed a winning account of elusive self-discovery…the results are refreshingly therapeutic."
                </Paragraph>
                <Paragraph FontSize="8">"</Paragraph>
                <Paragraph FontWeight="Bold" FontSize="12">– Frank Ochieng, World Voice News"</Paragraph>
              </Figure>
              Coping with the emotional and spiritual debris left by her horribly abusive childhood while simultaneously grappling with a seemingly endless parade of crises, Maggie decides its time to change her world by changing herself.
            </Paragraph>
            <Paragraph>
              She launches an improbable quest for spiritual rebirth by building a teepee in the woods behind her home in New England. Amidst the tall oaks, clawing blackberry brambles and voracious mosquitoes, she forges her own unique path to salvation. It’s not a traditional path, but it’s the only path Maggie can follow.
            </Paragraph>
            <Paragraph>
              <Floater Width="180" Background="Silver">
                <Paragraph IsHyphenationEnabled="True" FontSize="12"
                FontStyle="Italic" TextAlignment="Left">
                  "Marilyn’s life events, including her current day spiritual journey involving her family and the building of a backyard teepee, make for a reflective, honest and very touching story. It is a life of pain, reflection, tears, family and laughter, presented by someone who exhibits fine skills as a writer. Here is one book about life’s challenges and getting through them that will not only make you think … it will make you feel."
                </Paragraph>
                <Paragraph FontSize="8">
                </Paragraph>
                <Paragraph FontWeight="Bold" FontSize="12">– Jordan Rich, WBZ 1030AM, Host - "The Jordan Rich Show"</Paragraph>
              </Floater>
              As the teepee goes up, Maggie grows up. Better late than never, she finally frees herself from her haunted past. Her sense of humor lends her strength as she struggles up the rocky road to healing and peace.
            </Paragraph>
            <Paragraph>
              At the same time shocking, witty, raw and timely, "The 12-Foot Teepee" will keep you turning pages as Maggie’s quixotic journey of self discovery and healing unfolds.
            </Paragraph>
          </Section>
        </FlowDocument>
      </FlowDocumentReader>
    </Grid>
  </Grid>
</Page>

Posted in Presentations, Thoughts, Tutorials, WPF | 4 Comments »

.NET Source Code is available for public

Posted by Igor Moochnick on 01/17/2008

You can find all the details of how to configure your Visual Studio in a detailed Shawn Burke’s article. It looks like the WPF source can be in there too according to Bart hints on his B#.NET blog.

Posted in Software, Tutorials, Visual Studio | 1 Comment »

Technorati Profile

Posted by Igor Moochnick on 01/12/2008

Just joined Technorati. This is my Technorati Profile.

Posted in Uncategorized | Leave a Comment »

Free Silverlight training at Lynda.com

Posted by Igor Moochnick on 01/12/2008

lynda.comThanks to Mike Taulty’s post, I can add yet another great training video collection to my library – Silverlight Essential Training on Lynda.com.

I’ve already pointed your attention to Lynda.com’s free WPF training videos in one of my previous posts, so keep an eye on evergrowing great training resource.

Posted in Silverlight, Software, Tutorials | Leave a Comment »

Dynamic code generation

Posted by Igor Moochnick on 01/12/2008

To add to my previous post CodeDom extensions and dynamic LINQ. I’d like to mentions that the same technique can be used to generate/emit a valid compliable code.

Fore example the following snippet:

   1: var c = new CodeDom();
   2: c.AddNamespace("Samples").Imports("System")
   3:     .AddClass(
   4:       c.Class("TestClass")
   5:         .AddMethod(c.Method("PrintTest", "Console.WriteLine(\"Hello world !\");")));
   6: 
   7: string s = c.GenerateCode();

will generate the following code, which, at the end, can be written to a file or compiled in-memory:

   1: //------------------------------------------------------------------------------
   2: // <auto-generated>
   3: //     This code was generated by a tool.
   4: //     Runtime Version:2.0.50727.1433
   5: //
   6: //     Changes to this file may cause incorrect behavior and will be lost if
   7: //     the code is regenerated.
   8: // </auto-generated>
   9: //------------------------------------------------------------------------------
  10: 
  11: namespace Samples {
  12:     using System;
  13:
  14:
  15:     public class TestClass
  16:     {
  17:         public static void PrintTest()
  18:         {
  19:             Console.WriteLine(\"Hello world!\");
  20:         }
  21:     }
  22: }

So, unleash your imagination!

[The full source code with tests/examples you can find, as usual, on my web site: http://igor.moochnick.googlepages.com]

Posted in C#, Reflection, Tutorials | Leave a Comment »

 
%d bloggers like this: