Saturday, July 08, 2017

Type Erasure

Say that I have a view model that has a reference to a data source object generated by another object like a factory. In my view model I would have a property that is typed as AnyDataSource. I also have a property that is of type FRCDataSource, this is the object that will be wrapped in the AnyDataSource object.

class AddToDoViewModel {
    var dataSource : AnyDataSource<Item>!
    var frcDataSource : FRCDataSource<Item>!

FRCDataSource is defined as :

class FRCDataSource<T: NSManagedObject> : DataSourceProtocol {

    var fetchedResultsController : NSFetchedResultsController<T>!

    init(fetchedResultsController: NSFetchedResultsController<T>) {
    self.fetchedResultsController = fetchedResultsController
    }
}

The FRCDataSource class is a wrapper around an NSFetchedResultsController type. The generic type constraint on FRCDataSource limits the type of T to be an object that derives from NSManagedObject. Also note that FRCDataSource is specialized by the same type as NSFetchedResultsController. To create an FRCDataSource we do the following in reloadData()

func reloadData() {
    self.frcDataSource = FRCDataSource(fetchedResultsController:self.fetchedResultsController)
}

We create an FRCDataSource, passing in the NSFetchedResultsController class property. Now our frcDataSource property is set to a FRCDataSource instance that internally stores a NSFetchedResultsController instance. In this case, I am creating an instance of FRCDataSource directly, although I could easily delegate this responsibility to another object which would create and return an FRCDataSource.

Once I’ve created an FRCDataSource object from the NSFetchedResultsController, I can now add a method that will create an AnyDataSource derived object and store it in the dataSource property of the view model:

func createDataSource<T: DataSourceProtocol>(dataSource: T) where T.DataSourceItem == Item 
{
    self.dataSource = AnyDataSource(dataSource)
}

The createDataSource() takes an object that adopts the DataSourceProtocol, creates an AnyDataSource object and sets the dataSource property. There are a few things to take note of here:

Once the data source is created we will have an AnyDataSource typed object that can be used in place of a DataSourceProtocol type.

Basically what we’ve done is create wrappers for two types


Saturday, July 01, 2017

ProtocolOrientedProgramming

Type Erasure


Say that I have a view model that has a reference to a data source object generated by another object like a factory.  In my view model I would have a property that is typed as AnyDataSource<Item>.  I also have a property that is of type FRCDataSource<Item>, this is the object that will be wrapped in the AnyDataSource<Item> object.


class AddToDoViewModel {

var dataSource : AnyDataSource<Item>!

var frcDataSource : FRCDataSource<Item>!



FRCDataSource<Item> is defined as :  


class FRCDataSource<T: NSManagedObject> : DataSourceProtocol {


var fetchedResultsController : NSFetchedResultsController<T>!


init(fetchedResultsController: NSFetchedResultsController<T>) {

        self.fetchedResultsController = fetchedResultsController

}

}


The FRCDataSource<T> class is a wrapper around an NSFetchedResultsController<T> type.  The generic type constraint on FRCDataSource limits the type of T to be an object that derives from NSManagedObject. Also note that FRCDataSource<T> is specialized by the same type as NSFetchedResultsController<T>.  To create an FRCDataSource we do the following in reloadData()


func reloadData() {

self.frcDataSource = FRCDataSource(fetchedResultsController:self.fetchedResultsController)

}


We create an FRCDataSource, passing in the NSFetchedResultsController<T> class property.  Now our frcDataSource property is set to a FRCDataSource<Item> instance that internally stores a NSFetchedResultsController<Item> instance.  In this case, I am creating an instance of FRCDataSource directly, although I could easily delegate this responsibility to another object which would create and return an FRCDataSource.


Once I’ve created an FRCDataSource object from the NSFetchedResultsController, I can now add a method that will create an AnyDataSource<Item> derived object and store it in the dataSource property of the view model:


func createDataSource<T: DataSourceProtocol>(dataSource: T) 

where T.DataSourceItem == Item 

{

self.dataSource = AnyDataSource(dataSource)

}


The createDataSource<T>() takes an object that adopts the DataSourceProtocol, creates an AnyDataSource object and sets the dataSource property.  There are a few things to take note of here:


  • The createDataSource method is a generic method and is specialized by an object that must adopt DataSourceProtocol.  The input parameter dataSource is of the specialized type.
  • A generic constraint is specified which constrains the DataSourceItem associated type of the input parameter to be of type Item.  This is done to make sure that the type of the dataSource property matches the type returned by the AnyDataSource(dataSource) init call.


Now we just have to pass in the frcDataSource property to the createDataSource() method.


createDataSource(dataSource: self.frcDataSource)


Once the data source is created we will have an AnyDataSource typed object that can be used in place of a DataSourceProtocol type.  


Basically what we’ve done is create wrappers for two types of objects:

  1. An FRCDataSource<T: NSManagedObject> wrapper around a NSFetchedResultsController<T> type
  2. An AnyDataSource<T: DataSourceProtocol> wrapper around the DataSourceProtocol adopter FRCDataSource<T: NSManagedObject>


This allows external clients of AddToDoViewModel (e.g. UITableViewDataSource delegate objects) access to the AnyDataSource<Item> object without leaking the internal implementation of the data source of AddToDoViewModel (e.g. NSFetchedResultsController<Item>).  Knowing this, we can replace frcDataSource with another object that adopts DataSourceProtocol.  If I have a type that models data within sections called a DataSource,


class SectionController<T: NSManagedObject> : DataSourceProtocol {

    var sections : [SectionInfo<T>] = [] 

}


This class is used to represent objects stored in an array of SectionInfo<T> objects.  This enables us to create a custom data source that is not reliant on CoreData and relationships between CoreData entities.  I can create an array of SectionInfo<T> types like SectionInfo<Item> types and store them in the sections property.  This gives me a flexible way of storing data than what an NSFetchedResultsController provides since the fetchedObjects property of the NSFetchedResultsController are immutable.  Basically, the NSFetchedResultsController provides an immutable in-memory representation of the entities and relationships in a CoreData store.  If your desire is to re-order sections easily, you would need to create a new data store that structures the data the way that you want.


Let’s say that I would like a data source that models the following sections along with their respective items:


  • Errands 
  • Groceries
  • Post Office
  • Career
  • Presentation
  • Multiple Selections


I first create an array of SectionInfo<T> objects.  The SectionInfo<T> struct is defined as:


class SectionInfo<T : NSManagedObject> {

    var name : String = ""

    var rows : [T] = []

}


Each SectionInfo<T> has a name as well as an array of T types.  Lets create a method to create a section within the SectionController class:


extension SectionController {

    func createSection(name: String, items: [T]) {

        let section = SectionInfo<T>()

        section.name = name

        

        for item in items {

            section.rows.append(item)

        }

        

        self.sections.append(section)

    }

}


Now I can do the following:

  1. Create a property in AddToDoViewModel of type SectionController<Item>! called sectionDataSource
  2. Intitalize the sectionDataSource property with data by calling createSection() for each section
  3. Call createDataSource() which sets the dataSource property.


First add a property to AddToDoViewModel

class AddToDoViewModel {

var sectionDataSource : SectionController<Item>!


Create the SectionController<Item> instance in reloadData()

func reloadData() {

self.sectionDataSource = SectionController()

}


Create the sections in an initSectionData()

func initSectionData() {

self.sectionDataSource.createSection(name:”Errands”

, items: [Item(name:“Groceries”), Item(name:”Post Office”)])


self.sectionDataSource.createSection(name:”Career”,

items:[Item(name:“Presentation”), Item(name:”Multiple Selections”)]

}


Set the dataSource property

createDataSource(dataSource: self.sectionDataSource)


what we’ve done is create wrappers for two types of objects:

  1. A SectionController<T: NSManagedObject> wrapper around a SectionInfo<T> type
  2. An AnyDataSource<T: DataSourceProtocol> wrapper around the DataSourceProtocol adopter SectionController<T:NSManagedObject> type


Now that we’ve created the new data source, external clients (e.g. UITableViewDataSource delegate objects) can access this data store without any changes


Thursday, December 20, 2007

Derived classes and events

Events are a useful feature of the C# language and allow for clients to be notified when the state of a server changes. You create an event by declaring it in the class that will raise the event:

public event EventHandler NotifyClient;

Here, I used the generic event template to eliminate the need to define a separate delegate. To register a callback method with the event, we do the following in the class that will receive the event notification from the class that raised the event:

message.NotifyClient += new EventHandler(message_NotifyClient);

static void message_NotifyClient(object sender, EventArgs e)
{
throw new Exception("The method or operation is not implemented.");
}

When the event is raised the message_NotifyClient method will execute. To raise the event we add the following to the class that raises the event:

protected virtual void OnNotifyClient(EventArgs e)
{
EventHandler handler = NotifyClient;

if (handler != null)
handler(this, e);
}

Here, we make a copy of the event since access to the event is not thread-safe (i.e. another thread could delete/modify the event before the if (handler != null) completes). When the client wants to raise the event, it does so by executing the OnNotifyClient method:

private void DoSomething()
{
// Do something...
OnNotifyClient(new EventArgs());
}

When OnNotifyClient is executed, the message_NotifyClient method is executed.

Derived classes and events
An event can only be raised from methods declare within the class that declared the event. So events declared in class A can only be raised from methods within class A. By default, events are not inherited by derived classes, so in the following base class definition:

public class Base
{
public event EventHander NotifyClient;
}

with the derived class definition

public class Derived : Base
{
private void DoSomething()
{
EventHandler handler = NotifyClient;

if (handler != null)
handler(this, new EventArgs());
}
}

The derived class will not have access to the NotifyClient event since the NotifyClient event was not declared in the Derived class. There are two ways to workaround this requirement:
You'll notice above that the OnNotifyClient method is declared with the virtual keyword. This allows the Derived class to override the OnNotifyClient method and access the NotifyClient directly. So, we could do this in the Derived class:

protected override void OnNotifyClient(EventArgs e)
{
EventHandler handler = NotifyClient;

if (handler != null)
handler(this, e);
}

protected void DoSomething()
{
// Do something Derived-class specific, then call OnNotifyClient
OnNotifyClient(new EventArgs());
}

The second approach is to declare the event virtual in the Base class, then override the event in the Derived class:

public class Base
{
public virtual event EventHandler NotifyClient;
...
}

public class Derived : Base
{
public override event EventHandler NotifyClient;

public void DoSomething()
{
EventHandler handler = NotifyClient;

// Here, we can access the NotifyClient directly since we've overridden access
if (handler != null)
handler(this, new EventArgs());
}
}

Which approach you take is up to you. Both approaches give the Derived class the flexibility to perform Derived-specific tasks around the decision to raise the event. It really comes down to which approach is preferred.

Wednesday, November 28, 2007




When the pros of using reflection outweigh the cons, you can take advantage of using it when iterating over properties of classes.  To help with debugging, you can override the ToString() of your classes to return a string that contains the name of any public properties along with their corresponding values:

        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            Type t = this.GetType();

            PropertyInfo[] pInfo = t.GetProperties();

            sb.Append(t.ToString() + "\r\n");

            foreach (PropertyInfo p in pInfo)
            {
                string fmt = string.Format("{0} = {1}", p.Name, p.GetValue(this, null));

                sb.Append(fmt + "\r\n");
            }

            return sb.ToString();
        }

The function uses reflection to get the public properties of the class and it iterates over the collection of properties and builds a string that represents the state of the class.  The string returned from ToString() would look like this:

Property1 = Value1
Property2 = Value2
.
.
.

The PropertyInfo.GetValue() function takes two parameters; the first parameter is the reference to this, while the second parameter is an object array that is used when the PropertyInfo references an indexed property.  When using reflection to enumerate properties on a class that contains other classes, you must accomodate the case where a class might contain an indexed property:

public class Details
{
        public EDIProcess.Model.EstimateDetailType this[int index]
        {
            get { return (EDIProcess.Model.EstimateDetailType) DetailCollection[index]; }
        }
}

In this case, the Details class contains an indexer that is used to retrieve EstimateDetailType objects by index from the DetailCollection property.  You can use the GetValue() function and pass in an object array that contains a single entry that is the value of the offset into the collection, which will reference the indexed item at that position within the collection.

public class Details
{
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();

            try
            {
                Type t = this.GetType();
                string fmt;

                PropertyInfo[] pInfo = t.GetProperties();


                sb.Append(t.ToString() + "\r\n");

                foreach (PropertyInfo p in pInfo)
                {
                    if (p.Name == "Item")
                    {
                        for (int i = 0; i < Count; i++)
                        {
                            fmt = string.Format("{0} = {1}", p.Name, p.GetValue(this, new object[] { i }));
                            sb.Append(fmt + "\r\n");
                        }
                    }
                    else
                    {
                        fmt = string.Format("{0} = {1}", p.Name, p.GetValue(this, null));
                        sb.Append(fmt + "\r\n");
                    }
                }
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
            }

            return sb.ToString();
    }
}

The items in bold represent the changes to support the indexed properties.  The Details class contains a DetailCollection class (which derives from ArrayList), and the Details class contains an indexer to retrieve an item from the collection as well as a property that returns the number of items stored in the collection.  The modification looks for a property named Item in the Details class, and it then retrieves the count of objects in the collection and for each object in the collection it calls the GetValue(), passing in a reference to the Details class (this) and a new object[] array that contains a single member that stores the integer value of the item within the collection.




Friday, September 21, 2007

Threading in C#

I found an interesting online resource on Threading in C#

Friday, November 03, 2006

On the project that I am leading, I ran across an interesting issue using a combination of a stored procedure and the ISNULL SQL function. If we have the following table definition:

CREATE TABLE [dbo].[TEST_TABLE] (
[Data] [varchar] (5) COLLATE Latin1_General_BIN NOT NULL
)


and this table contains a row that contains:

Data
=====

ABCDE


Now, if we have a stored procedure that updates the row called UpdateData:

CREATE PROCEDURE UpdateData
@Data varchar(3) = null
AS

Begin Tran
update TEST_TABLE
set Data = ISNULL(@Data, Data)
IF @@ERROR <> 0
Rollback Tran
else
Commit Tran

The stored procedure sets the @Data variable to null by defualt, otherwise it will use the value passed to it via the @Data variable. The update statement uses the ISNULL function to check if the @Data variable is the default value of null and if it is, then it should use the current value in the Data column on the table. If we call this stored procedure, without passing in the @Data parameter, the stored procedure will set the value of the @Data parameter to null, and this is what we'll get:

Data
=====
ABC


What happened, why did my data get truncated? Think about how the ISNULL function works, it sets the variable specified in the first parameter to the value of the variable specified in the second parameter if the first parameter is null. So, it should set the @Data variable to the value in the Data column. Also note that the stored procedure is implicitly creating the @Data variable in the procedure declaration and also note that the @Data variable has a width of 3 varchars instead of the 5 varchars in the TEMP_TABLE Data column declaration. Essentially what happens is that the ISNULL function sees that the @Data variable is null, reads the Data column from the table and then copies the value from the Data column into the @Data variable. Since the @Data variable is only 3 varchars wide, only 3 varchars are copied to it. The set clause then updates the Data column with these 3 varchars from the @Data variable. That's why the data gets truncated. So, the moral of the story is to make sure of the following:

Wednesday, October 04, 2006

SQL Server pseudo nested transactions

SQL Server 2000 does not support nested transactions. So, if we have the following two stored procedures:

SP1:

create procedure sp1
as

begin tran
exec sp2

if (@@error <> 0)
goto on_error

commit tran

on_error:
rollback tran



SP1:
create procedure sp2
as

begin tran
insert table values ('sp2')

if (@@error <> 0)
goto on_error

commit tran

on_error:
rollback tran


The rules for nested begin transactions is:
Basically, I think of nested transactions as really just one main transaction that could contain multiple time points where the state of the transaction (committed, rollback) can be modified.

When using the ADO.NET SqlTransaction object you need to be aware of how transactions are committed and rolled back. When the SqlTransaction.BeginTransaction method is executed, it implicitly executes the BEGIN TRAN SQL statement. Any SQL statements executed will then execute on this main transaction. If the SQL statements that are executed perform a commit or rollback, the main transaction is affected based on the rules above. There may be certain cases where a servere SQL error will cause the main transaction to rollback, and if the main transaction is created by the SqlTransaction.BeginTransaction method, when the exception is caught, you will need to check if the transacion was actually already rolled back before executing the SqlTransaction.Rollback method:


try
{
try
{
SqlTransaction txn = new SqlTransaction();

txn.BeginTransaction();

Data.CallSproc1();
Data.CallSproc2(); // throws an exception and rolls back the transaction
txn.CommitTransaction();
}
catch(SqlException ex)
{
txn.RollbackTransaction(); // If the transaction is already rolled back, this will throw an exception
}
}
catch(SqlException ex)
{
// Transaction was already rolled back, do something
}
}

This page is powered by Blogger. Isn't yours?