lundi 21 novembre 2011

C# WPF, Dynamic Loading / Late Binding / Reflection with AvalonEdit

The point here is to optionnaly allow to use AvalonEdit (formerly known as Avalon) in an (wpf) application.


The basics

Specific using:
using System.IO;
using System.Reflection;
using System.Xml; //only for "the not so basic"
As you can see, none of them concerns AvanlonEdit...

When to Load :
String AvalonEditDllName = "ICSharpCode.AvalonEdit.dll";
if ( File.Exists(AvalonEditDllName) ) {/*...*/}

How to load:
Assembly u = Assembly.LoadFile(Path.GetFullPath(AvalonEditDllName));

What to instanciate:
Type tAvalonEditTextEditor = u.GetType("ICSharpCode.AvalonEdit.TextEditor");
if ( tAvalonEditTextEditor != null ) {/*...*/}

How to instanciate:
System.Windows.UIElement aeui = 
    (System.Windows.UIElement)Activator.CreateInstance(tAvalonEditTextEditor);

From now, you can use your System.Windows.UIElement in your WPF form just like this:
MainGrid.Children.Add(aeui);
where MainGrid is, for example, a System.Windows.Controls.Grid.

The basics of properties

Do you want line numbers ?
First let's look for the property of the type :
PropertyInfo propShowLineNumbers = 
    tAvalonEditTextEditor.GetProperty("ShowLineNumbers");
Then let's make the property true :
propShowLineNumbers.SetValue(aeui, true, null);

The not so basic of properties

And what about syntax hihgligting ?? Good question indeed !
Some more types and properties:
Type tAvalonEditHightingLoader = 
    u.GetType("ICSharpCode.AvalonEdit.Highlighting.Xshd.HighlightingLoader");
Type tAvalonEditHightingManager = 
    u.GetType("ICSharpCode.AvalonEdit.Highlighting.HighlightingManager");

PropertyInfo propSyntaxHighlighting = tAvalonEditTextEditor.GetProperty("SyntaxHighlighting");
PropertyInfo spropAEHMInstance = tAvalonEditHightingManager.GetProperty("Instance");

And the loading himself (I try to keep the variables consistant with the previous pieces of code):
String XshdFileName = "t-sql.xshd";
using ( XmlTextReader reader = new XmlTextReader(XshdFileName) ) {
    propSyntaxHighlighting.SetValue( //let's set the property of the text editor
        aeui,
        tAvalonEditHightingLoader.InvokeMember(
            "Load", //by loading the xshd file with HightingLoader.Load
            BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static | 
                BindingFlags.InvokeMethod,
            null, null,
                   //with the following parameters
            new Object[] { reader, spropAEHMInstance.GetValue(null, null) }
                   //one of them being the static property
                   //HighlightingManager.Instance
        ),
        null
    );
 }

mercredi 2 novembre 2011

Sales Force and WCF

Hello,
The following is a 2 hours testing session resulting of the following sentence : "Our client wants to interface our Production tool with Sales Force...". Of course I heard of Sales Force before, but nothing more.
I assume that you have downloaded the wsdl file from your Sales Force Account.
Then you use the svcutil tool to generate your proxy class. Something like :
"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\x64\svcutil" *.wsdl /language:C#

From this point you should realise that svcutil gives you a cs file but also an app.config part to use in your project to configure the proxy class.
Then the following code should list, on the console, the Accounts of your Sales Force Application. In this code "Soap" is a "false friend" coming from my minimalistic svcutil command line.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;

namespace sfBySoap {
  class Program {
    static void Main(string[] args) {
      try {
        SoapClient sfClient = new SoapClient();
        String sfLogin = "***@***.***";
        String sfPassword = "***";
        String sfSecurityToken = "***";
        LoginResult lr = sfClient.login(
          null, 
          sfLogin, 
          sfPassword + sfSecurityToken);
        Console.WriteLine("{0}\r\n{1}",
            lr.sessionId, 
            lr.serverUrl);
        SoapClient sc = new SoapClient(
            "Soap", 
            new EndpointAddress(new Uri(lr.serverUrl)));

        SessionHeader sh = new SessionHeader();
        sh.sessionId = lr.sessionId;

        QueryResult qr = sc.query(
              sh, //SessionHeader
              null, //QueryOptions
              null, //MruHeader
              null, //PackageVersion
              "select NAME, DESCRIPTION, TYPE, " +
                  "CREATEDBYID from Account");

        while (true) {
          foreach (Account a in qr.records) {
              Console.WriteLine("{0} - {1}\r\n    :{2}",
                  a.Name,
                  a.Type,
                  a.Description);
          }

          if (qr.done) {
              break;
          } else {
              qr = sc.queryMore(sh, null, qr.queryLocator);
          }
        }

        //sfClient.logout();
        sc.Close();
        sfClient.Close();
      } catch (Exception ex) {
          ExToConsole(ex);
      }
    }

    static void ExToConsole(Exception ex) {
        if (ex != null) {
            Console.WriteLine(ex.Message);
            ExToConsole(ex.InnerException);
        }
    }
  }
}

Here it is.... you are connected to Sales Force.