Archive

Archive for the ‘Exploring the CodeFluent Runtime’ Category

Exploring the CodeFluent Runtime: ChunkedMemoryStream


 
Today, on the series “Exploring the CodeFluent Runtime” we are going to take a look at the ChunkedMemoryStream class on the CodeFluent.Runtime.Utilities namespace.
 
This class allows you to manipulate a memory stream by “chunks”. This can be useful when you are dealing with memory streams big enough (85,000 bytes) to be allocated on the Large Object Heap (LOH).
 
The ChunkedMemoryStream can be used instead of the System.IO.MemoryStream (mscorlib.dll) to avoid memory fragmentation.
 
Let’s build a simple example in order to compare the use of a System.IO.MemoryStream against the CodeFluent.Runtime.Utilities.ChunkedMemoryStream.
 
Let’s say I want to load a file’s content in memory (big enough to sit on the LOH).
 

static void Main(string[] args)
{
  FileStream fileSm = new FileStream(@"file_path", FileMode.Open);
  Stream ms = new MemoryStream();
  fileSm.CopyTo(ms);
  ms.Close();
  fileSm.Close();

  System.Diagnostics.Debugger.Break();
}

 
When the Debugger breaks let’s explore the LOH:
 

LOH using MemoryStream

LOH using MemoryStream


 
We can see that the LOH size is (17184 + 41943056 + 83886096 = 125846336 bytes) and we easily distinguish a memory allocation for 2 byte arrays (perhaps some buffers used internally when copying the data from one stream to another).
 
Let’s now change only one line in our code example and use the CodeFluent.Runtime.Utilities.ChunkedMemoryStream.
 

static void Main(string[] args)
{
  FileStream fileSm = new FileStream(@"file_path", FileMode.Open);
  Stream ms = new CodeFluent.Runtime.Utilities.ChunkedMemoryStream();
  fileSm.CopyTo(ms);
  ms.Close();
  fileSm.Close();

  System.Diagnostics.Debugger.Break();
}

 
And let’s explore the LOH:
 

LOH using ChunkedMemoryStream

LOH using ChunkedMemoryStream


 
We now see that the LOH size is 17184 bytes and we cannot see any trace of a byte array.
 

Using the ChunkedMemoryStream we avoid allocating memory on the LOH when manipulating big streams.

 
Remeber that the CodeFluent Runtime Client is a free library that provides very useful and powerful helpers like:

  • XML utilities
  • IO utilities
  • Type conversion helpers
  • JSON utilities
  • … and many other

 
You can easily install the CodeFluent Runtime Client from Nugget.
 
PM> Install-package CodeFluentRuntimeClient
 
 
Regards,
 
Pablo Fernadez Duran
 
 

Manipulating NTFS alternate data streams in C# with the CodeFluent Runtime Client

March 14, 2013 1 comment

Have you already heard about NTFS alternate streams? Also known as named streams or ADS (Alternate Data Streams).
Well it is a useful feature in NTFS storage systems. It expands the concept of file and data streams.

Alternate Data Streams

Alternate Data Streams

When working with NTFS files, the main data stream (or unnamed stream) is the central element of the file. When you create a file, a main stream is created. When you create an alternate stream and the main stream does not exist it is created, if you delete the main stream the whole file is deleted (so the existing alternate streams).
When you read a file or you write in to a file you are working with the main stream by default.

Alternate streams follows the syntax: “filename.ext:alternateName”

You can store any kind of data in an ADS (as you can do it with the unnamed stream), so you can store binary data, text data, an image, a video and even an executable file.

Let’s make quick test.

Open a command line console (cmd.exe).
Create a text file and write some content in it:

Writing in to the main data stream

Writing in to the main data stream

Let’s read the content:

Reading the main stream

Reading the main stream

Nothing extraordinary, we get the main data stream from our file.
Now let’s try to write in to an alternate data stream (this will create the alternate stream if it does not exist).

Writing in to an Alternate Data Stream

Writing in to an Alternate Data Stream

You have created an alternate data stream called “hide” right on our file “test.txt”, this will not have any incidence with your main data stream.
To ensure that our alternate data stream “hide” has been correctly created we will try to read it.

Reading an Alternate Data Stream content

Reading an Alternate Data Stream content

And to prove that our main data stream is still there, let’s read the main stream.

Reading the main stream

Reading the main stream

We have made some tests only with “text” streams but a stream can be also an image, an executable file and all other kind of stream a file container can host.
What about manipulating Alternate Data Streams with C#?
Well, this feature is unfortunately not available in .NET, we would need to call native methods if we want to manipulate alternate data streams.
So we can build some nice native method wrappers in order to manipulate alternate data streams or we can use the CodeFluent Entities Runtime Client.
CodeFluent Runtime Client is a free library that provides very useful and powerful helpers like:

  • XML utilities
  • IO utilities
  • Type conversion helpers
  • JSON utilities
  • … and many other

You can easily install the CodeFluent Runtime Client from Nugget.

PM> Install-package CodeFluentRuntimeClient

Using the CodeFluent Entities Client Runtime to manipulate alternate data streams is as easy as manipulate all well-known file streams.
We will use the NtfsAlternateStream class which is located in the CodeFluent.Runtime.BinaryServices namespace, it provides some static helper methods to manipulate alternate streams as they were “regular” streams (open, create, read, write, enumerate, delete…).
Let’s take a look to some useful methods to manipulate alternate data streams (ADS):

//Create a stream supporting ADS syntax
FileStream stream = NtfsAlternateStream.Open("test.txt:hide", FileAccess.Write, FileMode.OpenOrCreate, FileShare.None);
stream.Close();

//Writing in to an ADS
NtfsAlternateStream.WriteAllText("test.txt:hide", "Secret content");

//Reading data from an ADS
string text = NtfsAlternateStream.ReadAllText("test.txt:hide");

//Enumerating all the ADS in test.txt
IEnumerable adsStreams = NtfsAlternateStream.EnumerateStreams("test.txt");
foreach (NtfsAlternateStream ads in adsStreams)
{
    Console.WriteLine(ads.Name);
}

//This will not delete the test.txt file
NtfsAlternateStream.Delete("test.txt:hide");

A concrete example of how ADS are used in Windows is when you download a file from the Internet. When I open a file downloaded from the Internet with Word (2013) I receive a warning telling me that the file might not be secure.

Word Protected View

Word Protected View

How does Word know that I downloaded the file from the Internet? Well, every time you download a file, Windows set an ADS called “:Zone.Identifier” containing some data related to the origin of the file. Let’s confirm that.

string altFileName = @"C:\Users\pablo\Downloads\someDoc.docx:Zone.Identifier";
string content = NtfsAlternateStream.ReadAllText(altFileName);
Console.WriteLine(content);

What we get is:

ZoneTransfer ZoneId

ZoneTransfer ZoneId

This value “ZoneId=3” means that the file has “Internet” as origin.

If we delete the “:Zone.Identifier” ADS from the file:

string altFileName = @"C:\Users\pablo\Downloads\someDoc.docx:Zone.Identifier";
//this will not delete the file
NtfsAlternateStream.Delete(altFileName);

Now we don’t receive a warning when trying to open the file, Word has no information from the file origin.
Alternate data streams are nice but they have some limitations. As we have said, ADS are only supported in NTFS file storage systems so what happen if you copy a file containing ADSs to another file system (FAT file system, USB drive, CD/DVD, network transfer…)? Well, you will lose all your ADS!

Avoid writing important or critical data to alternate data streams. ADS are not supported in not NTFS file systems.

Some ideas where ADS might be useful:

  • If you are writing a program to edit images it will be nice to keep the original image (or even all the modification history) so the user can undo some changes. Instead of keeping separate files you can write all the image versions in the same file using ADS, e.g. image.jpg:original, image.jpg:v1
  • You can store thumbnails for graphical files.
  • Imagine you wrote a “reader” application, you can keep some information like: font size, current page, background color… in the file itself.

I am sure you can image other practical and fun uses for Alternate Data Streams, it would be great if you share it with us Winking smile.

Regards.
Pablo Fernandez Duran

CodeFluent Entities and JSON/REST

November 29, 2012 Leave a comment

In a previous post we announced that CodeFluent Entities natively support JSON/REST.

In this post we’re going to see how to take advantage of the generated JSON/REST architecture. Thanks to JSON WCF services we should be able to call server methods from the client of our choice. To illustrate that we’re going to create a back end application exposing JSON WCF services that will be consumed in a console application. As you’re going to see, all the hard work will be done by CodeFluent Entities.

Creating the solution

Start by creating a new CodeFluent Project. We’ll use the “ContactManager Sample Model” for the purpose of this article.ContactManagerModel

  • Add a new Class Library project named “ContactManager” to your solution. It will be used to host the generated files corresponding to your Business Object model and JSON WCF service’s contracts.
  • Add a new SQL Server Database project named “ContactManager.Persistence” to your solution. It will be used to host your generated SQL scripts.
  • Add a new Empty ASP.NET Website project named “ContactManager.BackEnd” to your solution and add a reference to the ContactManager project and create a “Services” folder. It will be used to host the JSON WCF Services.
  • Add a new Console Application project named “ContactManager.Client” to your solution and add a reference to the ContactManager project and to CodeFluent.Runtime.dll. We will use it to make some calls via JSON WCF to the backEnd application and display the results in the console. Also, by default, Microsoft Visual Studio 2010 sets the target framework to .NET Framework 4 Client Profile. Go to the property of your project and change its target to .NET Framework 4.
    image

Adding the producers

  • Add a Business Object Model Producer and set its Target Directory to the ContactManager project. Also add it a Service Object Model Sub Producer and configure it so JSON been enabled and no proxy been produced. This producer will generate the complete WCF-based communication layer (service, contracts) with native JSON/REST support.
  • Add a SQL Server Producer and set its target directory to the ContactManager.Persistence project.
  • Add a Template Producer and set its Target Directory to the the Services folder of your ContactManager.BackEnd project. Also set its Source Directory to “CodeFluent Entities installation folder > Modeler >Templates > ServiceModel > JsonWebServices > Services”.

Configuring the solution

Configure your solution so it first start your  ContactManager.BackEnd application and then your ContactManager.Client application.

Generating code

Now to start generating code, build your CodeFluent Entities project called ContactManager.Model.

Here is the visual studio solution you should have by now, each project containing the generated code (your database should have been created too):

ScreenShot051

Writing the client

When the WCF Service Object Model Producer is set to generate JSON web services, it automatically adds two extra operations to the Business Object model and Services:
1. JsonGet
2. JsonPost

As the name suggests, you can use those methods to read (JsonGet) or write (JsonPost) by calling any other operation available on the service.

So why not use the other operations directly instead?
Well you can (using HTTP POST method and the header Content-Type set to application/json), but what’s interesting with those JsonGet/Post methods is that they add extra JSON oriented features. One of them being able to wrap .NET exception in a nice and simple JavaScript-friendly object.

Note: JsonGet and JsonPost methods are not fully documented yet but a new version of the documentation is on its way.

Here we want to use the JsonGet method in our console application to call the default generated LoadAll method and write the result on the console:

we can break the task down to the following steps:

  • Set up the URL with all parameters
  • Send a GET WebRequest
  • Receive the Json formatted data
  • Deserialize the object(s)
  • Write the result on the console

Therefore, our console application should look something like this:

using System;
using System.Net;
using System.IO;
using CodeFluent.Runtime.Utilities;
using ContactManager;

namespace ContactManager.ConsolApp
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Type a key to start");
            Console.ReadKey();

            string url = "http://localhost:62738/Services/ContactManager.Customer.svc/JsonGet?method=LoadAll";
            string jsonContent = GET(url);

            //Let's display the RAW JSON content first:
            Console.WriteLine("JSON Content:");
            Console.WriteLine(jsonContent + Environment.NewLine);

            //Then each Customer:
            Console.WriteLine("From deserialized content:");
            CustomerCollection customers = JsonUtilities.Deserialize<CustomerCollection>(jsonContent);
            foreach (Customer c in customers)
            {
                Console.WriteLine(c.Trace());
            }
        }

    }
}

Notes: the URL should be changed according to your configuration (port number, and service name should be updated);

The GET method simply downloads and returns the internet string response as follow:

// Returns JSON string
private static string GET(string url)
{
    using (WebClient client = new WebClient())
    {
        try
        {
            return client.DownloadString(url);
        }
        catch (WebException ex)
        {
            WebResponse errorResponse = ex.Response;
            using (Stream responseStream = errorResponse.GetResponseStream())
            {
                StreamReader reader = new StreamReader(responseStream, new System.Text.UTF8Encoding());
                String errorText = reader.ReadToEnd();

                Console.WriteLine(errorText);
            }
            throw;
        }
    }
}

But where do we find the JSON Serializer? Well the CodeFluent Runtime (CodeFluent.Runtime.dll) comes with a very convenient class: JsonUtilities.
The JsonUtilities class is a simple yet powerful JSON Serializer allowing you to convert your .NET objects into JSON and vice versa. See that post for more information.

Running the application

Hitting Ctrl+F5 should build and launch your backend application and then your console application. Typing a key should retrieve all the customers using JSON WCF services and display them on the console as follow:

Type a key to start
JSON Content:
[{"EntityKey":"1","EntityDisplayName":"info@softfluent.com","RowVersion":[0,0,0,0,0,0,7,209],”Id”:1,”EmailAddress”:”info@softfluent.com”,”Password”:null,
“FirstName”:”Thib”,”LastName”:”Nes”,”FullName”:null,”BirthdayDate”:”\/Date(-62135596800000)\/”,”LoyaltyProgramMember”:false,”LicenseNo”:null,”HasPreAccidents”:false,
“Age”:0,”AddressId”:-1,”Rentals”:[],”PaymentType”:0,”EntityState”:1}]

From deserialized content:
[Id=1,EmailAddress=info@softfluent.com,Password=,FirstName=Thib,
LastName=Nes,FullName=,BirthdayDate=1/1/0001 12:00:00 AM,LoyaltyProgramMember=False,LicenseNo=,HasPreAccidents=False,Age=0,
Address=<null>,_addressId=-1,Rentals=[Count=0],PaymentType=Cash, EntityState=Unchanged]
Press any key to continue . . .

 

What about saving data? Well, we would use the JsonPost method instead of JsonGet and use the JsonUtilities.Serialize method to serialize our content. The Main method of our console application would look like this:

static void Main(string[] args)
{
    string url = "http://localhost:62738/Services/ContactManager.Customer.svc/JsonPost?type=EntitySaveCall";
    Customer c = new Customer { FirstName = "John", LastName = "Doe", Age = 42 };
    string jsonContent = JsonUtilities.Serialize(c);
    
    POST(url, jsonContent);
}

And the POST method to send the data:

// POST a JSON string
private static void POST(string url, string jsonContent)
{
    using (WebClient client = new WebClient())
    {
        string response = string.Empty;
        //We need to specify that we are sending Json contents, or our
        //requests will be rejected by the services
        client.Headers.Add("Content-Type: json; charset=UTF-8");
        client.Encoding = System.Text.Encoding.UTF8;
        try
        {
            response = client.UploadString(url, jsonContent);
        }
        catch (WebException ex)
        {
            WebResponse errorResponse = ex.Response;
            using (Stream responseStream = errorResponse.GetResponseStream())
            {
                StreamReader reader = new StreamReader(responseStream, new System.Text.UTF8Encoding());
                String errorText = reader.ReadToEnd();

                Console.WriteLine(errorText);
            }
            throw;
        }
    }
}

This is it! This post highlighted the fact that we can directly consume JSON WCF services generated by CodeFluent Entities from the client of our choice (for instance for Windows Phone, iOS or Android to name but a few). CodeFluent Entities doing all the hard work for us by generating applications based on REST/JSON architecture in a couple of minutes.

Hope this helps!

Cheers,

Thibault NESTOR

Exploring the CodeFluent Runtime: ZipFile

August 24, 2012 Leave a comment

Since the day it was born, the CodeFluent Entities Runtime embarks a cool ZipFile class that allows you to create .ZIP files from other files, directories and streams, and extract from .ZIP files files, directories of files and streams!

The class is found in the CodeFluent.Runtime.Compression namespace and is very easy to use:

using CodeFluent.Runtime.Compression;

namespace ZipTest
{
    class Program
    {
        static void Main(string[] args)
        {
            // compress
            using (ZipFile file = new ZipFile("newzip.zip", ZipFile.Mode.Overwrite))
            {
                file.AddFile(myFile1);
                file.AddFile(myFile2);
                file.AddDirectory(myDirectory); // recursive, keep relative paths in
            }

            // decompress
            using (ZipFile file = new ZipFile("newzip.zip", ZipFile.Mode.Read))
            {
                file.GetFiles(myOutputDirectory); // recursive, keep relative paths out
            }
        }
    }
}

For CPU performance and memory usage reasons, and contrary to other popular .NET zip implementations (http://www.icsharpcode.net/opensource/sharpziplib/, or http://dotnetzip.codeplex.com/), CodeFluent Entities’ ZipFile implementation is unmanaged.

It means you will have to copy a native Windows DLL (that is shipped with the product) named “CodeFluent.Runtime.Compression.dll” in the bin directory of your application for this to work. Since it’s unmanaged, there are two versions of this dll, one for X86 processes, and another for X64 processes.

It’s fun to see Microsoft has finally taken the same unmanaged route for ZIP handling, this year, in 2012, as we did 7 years ago, when we shipped our first version of CodeFluent Entities :-)

The CodeFluent Runtime is available in two flavors:

Happy zip-ing!

The R&D team.

Exploring the CodeFluent Runtime: Reusing a Script Engine (like JScript or VBScript) with .NET

August 6, 2012 Leave a comment

Following our “Exploring the CodeFluent Runtime“ post series, I thought I’d share with you another cool class available in the CodeFluent Runtime which is the ScriptEngine class.

The ScriptEngine class is a which wraps Windows Scripting Engines so you can easily and quickly reuse them with .NET code. The most useful engine is of course JScript which is Microsoft’s JavaScript implementation. JScript is installed on every Windows and is the exact same engine that is used by Internet Explorer. VBScript is also shipped out-of-the-box with every Windows installation and our ScriptEngine class indeed supports it. It should (this has not tested though) also support other scripting engines like ActivePython, ActivePerl, etc.

Here are some simple JavaScript examples that demonstrate how to leverage these engines:

Console.WriteLine(ScriptEngine.Eval("jscript", "1+2+3"));
// will output 6 (of Int32 type)

Console.WriteLine(ScriptEngine.Eval("jscript", "1.2"));
// will output 1.2 (of Double type)

Console.WriteLine(ScriptEngine.Eval("jscript", "1+2+3+'hello'"));
// will output 6hello (of String type)

You can also use external objects with these engines. Here I declare a Customer class (Note the ComVisible attribute set to true, this is mandatory as Script Engines are COM objects):

[ComVisible(true)]
public class Customer
{
    public string Name { get; set; }
}

And I reuse it directly in JavaScript using my ScriptEngine class:

            Customer customer = new Customer();
            customer.Name = "Joe";
            Console.WriteLine(ScriptEngine.Eval("jscript", "MyObj.Name", new KeyValuePair<string, object>("MyObj", customer)));
            // will output Joe (of String type)

You can also pre-parse a script text and run it when you want. This is better in terms of performance since the script will only be parsed once. Here is how you can do it, with a JavaScript method declared in the script source:

            ScriptEngine engine = new ScriptEngine("jscript");
            ParsedScript preParsed = engine.Parse("function MyMethod(arg1, arg2){return arg1*2 + arg2.Name}");
            Console.WriteLine(preParsed.CallMethod("MyMethod", 1, customer));
            // will output 2Joe (of String type)

If you want to externalize business rules (for example tax computation in a LOB app), or if you want to ensure your application supports higher level programming capabilities (like if you’re writing a game that needs some parts to be scriptable), this is a cool way to do it. Just provide an object model (like the Customer class in my example) as a programming facade to your users and they will be capable of programming your app. No need to understand complex Lex/Yacc/BNF syntax, to redefine the JavaScript syntax. Just reference the CodeFluent Runtime and here you go.

The CodeFluent Runtime is available in two flavors:

Cheers,

The R&D Team.

CodeFluent Runtime Client available on NuGet

May 16, 2012 1 comment

A few months ago we released the CodeFluent Runtime as a NuGet package so developers could benefits from its features (e.g. JSON Serializer, WinForms Wizard control, EditableUri, Utilities, etc.) in their .NET projects.

Today we’re pleased to announce a new package replacing the previous one: the CodeFluent Runtime Client!

It’s basically the same as the previous one with new controls (yay! a ribbon menu!) and most importantly supporting the .NET 4 Client Profile on top of supporting all .NET Framework versions from 2 and upper, across all technologies (WPF, WinForms, ASP.NET, consoles, services, SharePoint, etc.).

CodeFluentRuntimeClientPackage

Just like last time, it’s all free and it’s all happening on NuGet Winking smile

 

Cheers,

Carl Anderson

Dates and JSON

March 7, 2012 Leave a comment

JSON (JavaScript Object Notation) is a lightweight text-based open standard designed for human-readable data interchange (source: Wikipedia).

JSON is so very handy but one thing I hate about JSON is that its spec is so lightweight that it sometimes lacks some details on specific areas such as for dates. Scott Hanselman’s post “On the nightmare that is JSON Dates. Plus, JSON.NET and ASP.NET Web API”, is actually a perfect example of the kind of troubles you run into when building web sites and using various JSON serializers.

We bumped into this as we’re working on the next version of our ASP.NET Web Producer which will ship with an Ajax web site template (JQuery + JqGrid + JSON/REST) allowing developers to generate business oriented web apps (see our roadmap post for more info on this subject).

Anyway, when developing a business web site we, developers, have to support dates and since their format can vary in JSON, our JSON serializer/deserializer class (named JsonUtilities) supports several:

So if ever you need to support several date formats without having to switch JSON serializers/deserializers for each scenario, keep this JsonUtilities class in a corner as I’m sure it’ll come handy.

By the way, this JsonUtilities class is shipped as part of a free NuGet package, independently from our product, named CodeFluentRuntimeClient.

Here’s it’s web page if you want to try it out (http://nuget.org/packages/CodeFluentRuntimeClient) and here’s a post containing some serialization examples (JsonUtilities – Part 2) Winking smile

 

Cheers,

Carl Anderson

CodeFluent Runtime now available on NuGet Gallery

February 17, 2012 1 comment

The CodeFluent Runtime is a library of utilities which is usable across all types of .NET applications (WPF, WinForms, ASP.NET, console, service, etc.) and aims to ease the developer’s life. Until now it was only distributed as part of CodeFluent Entities, but starting today it is now shipped as a NuGet package on the NuGet Gallery!

This means that from now on, you can leverage utilities of the runtime – such as its JSON serializer/deserializer for instance Winking smile – from any .NET project regardless if you’re using CodeFluent Entities or not.

If you’re new to NuGet, here’s an overview: http://docs.nuget.org/docs/start-here/overview

Once you have NuGet, search for the CodeFluentRuntime package and add it to your project: it’s free Smile
Update: The CodeFluent Runtime package was replaced by the CodeFluent Runtime Client package (free as well, containing the same features, but lighter and supporting .NET Framework 4 Client Profile). Therefore, search for the new package “CodeFluentRuntimeClient” instead!

image

Cheers,

Carl Anderson

Exploring the CodeFluent Runtime: AutoObject

February 8, 2012 Leave a comment

Following our “Exploring the CodeFluent Runtime“ post series, I thought I’d share with you another cool class available in the CodeFluent Runtime which is the AutoObject class.

The AutoObject class is a light class which implements INotifyPropertyChanged and IDataErrorInfo so you can easily and quickly create classes data-binding and validation friendly classes.

Here’s how it works: say you need a small technical class for UI purposes. You want it to support data-binding and to raise an event when a property is changed, plus since your working in the UI, you might at some point need to validate user input. Instead of implementing those interfaces myself, I can derive from the AutoObject class which will provide those features for me.

Data-Binding (INotifyPropertyChanged):

Across .NET platforms (e.g. Windows Forms, WPF) a lot of .NET controls provided by Microsoft or third parties (e.g. Infragistics) use this interface to update the UI to reflect changes in the model. Here’s how to use the AutoObject to benefit from those features:

public class CustomerLight : AutoObject
{
    public CustomerLight()
    {
    }

    public string FullName
    {
        get
        {
            return GetProperty();
        }
        set
        {
            SetProperty(value);
        }
    }

    public string FullAddress
    {
        get
        {
            return GetProperty();
        }
        set
        {
            SetProperty(value);
        }
    }

}

And that’s it! Since the AutoObject implements the INotifyPropertyChanged interface for me, I can data-bind my UI to it easily. In fact, here’s a sample console application which prints received PropertyChanged events on the command line:

class Program
{
    private static CustomerLight _cv;

    static void Main(string[] args)
    {
        _cv = new CustomerLight();
        _cv.PropertyChanged += new PropertyChangedEventHandler(OnCustomerLightPropertyChanged);

        Console.WriteLine("Type-in customer full name:");
        _cv.FullName = Console.ReadLine();
        Console.ReadKey();
    }

    static void OnCustomerLightPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        Console.WriteLine("PropertyChanged: " + e.PropertyName);
    }
}

Here’s the result:

Type-in customer full name:
John Doe
PropertyChanged: FullName

Data Validation (IDataErrorInfo):

It’s exactly the same as for INotifyPropertyChanged, lots of UI control provide nice UI validation features if you implement this interface, and here’s how to do it using the AutoObject:

public class CustomerLight : AutoObject
{
    public CustomerLight()
    {
    }

    public string FullName
    {
        get
        {
            return GetProperty();
        }
        set
        {
            SetProperty(value);
        }
    }

    public string FullAddress
    {
        get
        {
            return GetProperty();
        }
        set
        {
            SetProperty(value);
        }
    }

    protected override void Validate(IList errors, string memberName)
    {
        // If no memberName, validate all members.
        if (string.IsNullOrEmpty(memberName) || memberName == "FullName")
        {
            if (FullName.IndexOfAny(new char[] { '!', '*', '@', '?' }) != -1)
            {
                errors.Add("Invalid name: the following characters are considered invalid: '!*@?'.");
            }
        }
    }
}

And we’ll update our console application to retrieve the validation error and print it if any:

static void OnCustomerLightPropertyChanged(object sender, PropertyChangedEventArgs e)
{
    Console.WriteLine("PropertyChanged: " + e.PropertyName);

    string error = ((IDataErrorInfo)_cv).Error;
    if (string.IsNullOrEmpty(error))
        return;

    Console.WriteLine(error);
}

And here’s the result:

Type-in customer full name:
test*test
PropertyChanged: FullName
Invalid name: the following characters are considered invalid: ‘!*@?’.

Hope this helps,

Carl Anderson

Exploring the CodeFluent Runtime: JsonUtilities – Part 2

January 6, 2012 1 comment

This post follows the “Exploring the CodeFluent Runtime: JsonUtilities” post, in which we introduced the JsonUtilities class as well as its Serialize method.

In addition to serializing objects, you can also use the class to deserialize JSON such as this:

string s = JsonUtilities.Serialize(new string[] { "1", "2" });
List<int> list = JsonUtilities.Deserialize<List<int>>(s);

Running the code above, you’ll get a list of integers out of the JSON string as expected.

Another cool feature is that the serializer, on top of serializing all types such as byte[], guid, long, etc., can serialize anonymous types, you don’t have to use strongly typed objects:

s = JsonUtilities.Serialize(new
{
    MyDateAtt1 = DateTime.Now,
    MyEnumAtt2 = UriKind.RelativeOrAbsolute,
    MyBytes = new byte[] { 0xDE, 0xAD, 0xBE, 0xEF },
    MyGuidAtt = Guid.NewGuid()
});

And then, when deserializing, we can use a strong type such as the MyType class, declared as follows:

public class MyType
{
    public DateTime MyDateAtt1; // field support
    public Guid MyGuidAtt { get; set; } // guid support
}

And here’s the code deserializing our anonymous type into a MyType type:

MyType mt = new MyType();
JsonUtilities.Deserialize(s, mt, JsonSerializationOptions.Default | JsonSerializationOptions.UseReflection); // sets props & fields

Properties which don’t exists (e.g. MyEnumAtt2 and MyBytes) will be skipped without raising an error.
Carl Anderson

Follow

Get every new post delivered to your Inbox.

Join 694 other followers

%d bloggers like this: