Google
 

Saturday, June 02, 2007

Using Platform Invoke (P/Invoke) in C#

A wiki for .NET developers

http://www.pinvoke.net/

.NET: Calling Win32 DLLs in C# with P/Invoke
http://msdn.microsoft.com/msdnmag/issues/03/07/NET/

Using the [assembly: CLSCompliant(true)] attribute in C#

You can apply the CLSCompliant attribute on an assembly (or just about any other program element) and have the compiler check if your code is CLS (Common Language System) compliant (which means it works properly when consumed by other .NET languages). For example, we place the following attribute in all MM .NET AssemblyInfo.cs files:

[assembly: CLSCompliant(true)]

Here are some of the things the compiler checks:

  • Class and member names cannot differ only by case. For example, you can't have one property named Counter and another named counter. This is important for cross-language compatibility since VB .NET isn't case sensitive.
  • Overloaded class methods cannot differ only by out or ref parameter designations.
  • Publicly exposed members cannot start with an underscore ( _ ).
  • Operators can't be overloaded
  • Unsigned types can't be part of the public interface of a class

Unfortunately, although you can apply the CLSCompliant attribute in VB .NET, the VB .NET compiler doesn't check for CLS compliance.

Sample Code:
Note: The exception that is not cls-compliant will not always be thrown and it depends on your compiler settings. If there is no compile exception, a warning will be.
When run the following code in SharpDevelop, both exception and warning will not be thrown.


[CLSCompliant(true)]
public class MyClass
{
public UInt32 Abc() { return 0; }

[CLSCompliant(
false)]
public void abc() { }

private UInt32 ABC() { return 0; }
}


REF:
http://msmvps.com/blogs/kevinmcneish/archive/2004/08/18/12025.aspx
http://www.devarticles.com/c/a/C-Sharp/Making-Your-Code-CLS-Compliant/

Free ebook download sites

  1. http://2020ok.com/
2.http://cooldogebooks.blogspot.com/

3.http://www.cnshare.org/

4.http://novian.web.ugm.ac.id/index.html
--
Happy day, happy life!

Access Scope in C#

  1. private        : can be called only by the objects in the same type
  2. protected    : can be called by objects the derived type, no matter in the same assembly or not
  3. public          : can be called by all code
  4. internal       : can be called by the code in the same assembly
  5. protected internal : same as protected
  6. internal protected : not support in C# but in IL it meas the derived type in the same assembly can call the code

--
Happy day, happy life!

Friday, June 01, 2007

Custom Business Object Implemented in C#


using  System;
using System.Collections.Generic;
using  System.Text;
using System.Data;
using System.Collections ;
using System.Reflection;

namespace COW.Business
{
    
/// <summary>
    
/// The Custom Business Object is used to fill business object or objects with IDataReader
    
/// The properties will be cached once they have been retrieved
    
///  </summary>
    public  class CBO<T>
    {
        
public CBO()
        { }
        
///  <summary>
        
/// Using reflectiong, to fill object with data in data reader
        
/// </summary>
        
/// <param name="reader"></param>
        
/// <param name="isManagedReader"> If the data reader is managed by others</param>
        
///  <returns></returns>
         public  T FillObject(IDataReader reader,bool isManagedReader)
        {
            
if (reader ==  null)
                
return default (T);

            
try
            {
                
//  get properties 
                IList<PropertyInfo > properties = RetrieveProperties();
                
// confirm each property index in data reader
                IList<int> ordinals  = GetOrdinal(reader, properties);
                
// check if data reader is managed
                if (isManagedReader)
                {
                    
return CreateObject(reader, properties, ordinals);
                }
                
else
                {
                    
try
                    {
                        
while (reader.Read())
                        {
                            
return  CreateObject(reader, properties, ordinals);
                        }
                        
throw  new Exception("The data read is null! ");
                    }
                    
finally
                    {
                        
if (reader !=  null)
                        {
                            reader.Close();
                        }
                    }
                }
            }
            
catch (Exception ex)
            {
                COW.Common.Exceptions.LogException(ex);
                
return default(T);
            }            
        }
        
/// <summary>
        
///  Using reflectiong, to fill object with data in data reader
        
/// The reader is not managed by others
        
/// </summary>
        
/// <param name="reader"></param>
        
/// <returns></returns>
        public T FillObject(IDataReader reader)
        {
            
return FillObject(reader,false);
        }

        
private T CreateObject(IDataReader reader, IList<PropertyInfo > properties, IList<int>  ordinals)
        {
            T target 
= Activator.CreateInstance< T>();
            
object propertyValue  = null;
            
// create an object instace and set each property with its value in data reader
             for (int i  = 0; i <  properties.Count; i++)
            {                
                
if  (-1 == ordinals[i])
                {
                    
// the property is not existing in data reader
                    continue;
                }
                PropertyInfo property 
= properties[i];
                
if ( !property.CanWrite)
                {
                    
// the property is readonly
                    continue;
                }
                
// set writable propertiy's value           
                try
                {
                    
//  set db null value                    
                    if  (reader[ordinals[i]].GetType().Equals( typeof(System.DBNull)))
                    {
                        property.SetValue(target,
null,null);
                    }
                    
else
                    {                    
                        
//  implicitly convert
                        property.SetValue(target, reader[ordinals[i]],  null);                    
                    }                    
                }
                
catch
                {
                    Type propertyType 
= property.PropertyType;
                    
// business object member type does not match the data member's type
                    
//  TODO: here to handle the enumeration type 
                    
// try explicitly convert                
                    
// if the type is nullable
                     if (propertyType.IsGenericType)
                    {
                        property.SetValue(target, Convert.ChangeType(reader[ordinals[i]],  propertyType.BaseType), 
null);
                    }
                    
else  if (propertyType.IsEnum)
                    { 
                        
//  nothing
                    }
                    
else
                    {
                        property.SetValue(target, Convert.ChangeType(reader[ordinals[i]], propertyType), 
null );
                    }
                }
            }
            
// return the object
            return target;
        }
        
/// <summary>
        
///  Get the property's index order in data reader
        
///  </summary>
        
/// <param name="reader"></param>
        
/// <param name="properties"></param>
        
/// <returns></returns>
        private List <int> GetOrdinal(IDataReader reader, IList< PropertyInfo> properties)
        {            
            
// check property name
            List< int> ordinals =  new List<int >();
            
if (reader !=  null)
            {
                
for ( int i = 0 ; i < properties.Count; i++ )
                {
                    
int ordinal =  -1;
                    
try
                    {
                        ordinal 
= reader.GetOrdinal(properties[i].Name);
                    }
                    
catch
                    { }  
                    ordinals.Add(ordinal);
                }
            }
            
return ordinals;
        }
        
///  <summary>
        
/// Using reflection, to fill a collection of object with data in data reader
        
/// </summary>
        
/// <param name="reader"></param>
        
/// <param name="objectType"></param>
        
/// <returns></returns>
        public  IList< T> FillCollection(IDataReader reader)
        {
            
//  create object collection
            List<T > collection =  new List<T> ();
            
if (reader ==  null)
            {
                
return collection;
            }
            
try
            {
                
while (reader.Read ())
                {
                    
// foreach item in data reader
                    
// fill an object with the item
                    T target  = FillObject(reader, true);
                    
// add the filed object to collection
                    collection.Add(target);
                }
                
if (reader !=  null)
                {
                    reader.Close();
                }
                
//  return the collection
                return collection;
            }
            
catch (Exception ex)
            {
                COW.Common.Exceptions.LogException(ex);
                
return collection;
            }
            
        }
        
///  <summary>
        
/// Retrieve the properties of T by reflection
        
/// </summary>
        
/// <param name="t"></param>
        
/// <returns></returns>
        private static  IList<PropertyInfo> RetrieveProperties()
        {
            
// get object properties in cache
            List<PropertyInfo> properties  = (List<PropertyInfo >)Cache.GetObject(typeof(T).FullName);

            
// retrieve object properties when that are not cached
             if (properties == null )
            {
                properties 
= new  List<PropertyInfo>();
                
foreach (PropertyInfo property in  typeof(T).GetProperties())
                {
                    properties.Add(property);
                }
                
//properties.AddRange(typeof(T).GetProperties);
                
// cache it
                Cache.SetObject(typeof(T).FullName, properties);
            }
            
return properties;
        }
    }
}


--
Happy day, happy life!

To create object in MS Access by Sql Script

[TestClass]
public class AccessSqlScriptTest
{
public AccessSqlScriptTest()
{
//
// TODO: Add constructor logic here
//
}

#region Additional test attributes
//
// You can use the following additional attributes as you write your tests:
//
// Use ClassInitialize to run code before running the first test in the class
// [ClassInitialize()]
// public static void MyClassInitialize(TestContext testContext) { }
//
// Use ClassCleanup to run code after all tests in a class have run
// [ClassCleanup()]
// public static void MyClassCleanup() { }
//
// Use TestInitialize to run code before running each test
// [TestInitialize()]
// public void MyTestInitialize() { }
//
// Use TestCleanup to run code after each test has run
// [TestCleanup()]
// public void MyTestCleanup() { }
//
#endregion

[TestMethod]
[Ignore]
public void CreateTable()
{
/// create table
const string TABLE_NAME = "Tab1";
string cmdText = string.Format(@"Create Table {0} (
ID Counter,
Name string,
Age integer,
[Date] DateTime);
", TABLE_NAME);
AccessHelper.ExecuteNonQuery(Config.ConnectionString, cmdText);

// create index
//string indexName = "iName";
//cmdText = string.Format(@"Create Index {0} ON {1} ([Name]); ", TABLE_NAME, indexName);
//AccessHelper.ExecuteNonQuery(Config.ConnectionString, cmdText);

// create unique index
//string indexID = "iID";
//cmdText = string.Format(@"Create Unique Index {0} ON {1} ([ID]); ", TABLE_NAME, indexID);
//AccessHelper.ExecuteNonQuery(Config.ConnectionString, cmdText);

//// drop index
//cmdText = string.Format(@"Drop Index {0} ON {1};",indexID,TABLE_NAME);
//AccessHelper.ExecuteNonQuery(Config.ConnectionString, cmdText);
//cmdText = string.Format(@"Drop Index {0} ON {1};", indexName, TABLE_NAME);
//AccessHelper.ExecuteNonQuery(Config.ConnectionString, cmdText);

// drop table
cmdText = string.Format(@"Drop Table {0};", TABLE_NAME);
AccessHelper.ExecuteNonQuery(Config.ConnectionString, cmdText);
}
[TestMethod]
[Ignore]
public void CreateStoreProcedure()
{
// creat store procedure
const string procedureName = "CreateStoreProcedureTest";
string cmdText = string.Format(@"CREATE PROC {0} AS SELECT * FROM t_Cow;"
, procedureName);
AccessHelper.ExecuteNonQuery(Config.ConnectionString, cmdText);

// drop store procedure
cmdText = string.Format(@"Drop PROC {0};", procedureName);
AccessHelper.ExecuteNonQuery(Config.ConnectionString, cmdText);
}
[TestMethod]
[Ignore]
public void CreateStoreProcedureWithParams()
{
// creat store procedure
const string procedureName = "CreateStoreProcedureWithParamsTest";
string cmdText = string.Format(@"CREATE PROC {0} ([@ID] Short) AS SELECT * FROM t_Cow WHERE ID=[@ID];"
, procedureName);
AccessHelper.ExecuteNonQuery(Config.ConnectionString, cmdText);

// drop store procedure
cmdText = string.Format(@"Drop PROC {0};", procedureName);
AccessHelper.ExecuteNonQuery(Config.ConnectionString, cmdText);
}
[TestMethod]
[Ignore]
public void AlterTableTest()
{
/// create table
const string TABLE_NAME = "Tab1";
string cmdText = string.Format(@"Create Table {0} (
ID Counter,
Name string,
Age integer,
[Date] DateTime);
", TABLE_NAME);
AccessHelper.ExecuteNonQuery(Config.ConnectionString, cmdText);
// add column
//ALTER TABLE [表名] ADD [字段名] INT
const string NewColumn = "NewColumn";
cmdText
= string.Format(@"Alter Table {0} ADD [{1}] INT", TABLE_NAME, NewColumn);
AccessHelper.ExecuteNonQuery(Config.ConnectionString, cmdText);

// update column
//ALTER TABLE [表名] ALTER COLUMN [字段名] [字段类型]

// if not specified the text length, the column will be created as Memo type : Alter Table {0} Alter Column [{1}] Text;
cmdText = string.Format(@"Alter Table {0} Alter Column [{1}] Text(200);", TABLE_NAME, NewColumn);
AccessHelper.ExecuteNonQuery(Config.ConnectionString, cmdText);

// delete column
//ALTER TABLE [表名] DROP COLUMN [字段名]

cmdText = string.Format(@"Alter Table {0} Drop Column [{1}];", TABLE_NAME, NewColumn);
AccessHelper.ExecuteNonQuery(Config.ConnectionString, cmdText);

// drop table
cmdText = string.Format(@"Drop Table {0};", TABLE_NAME);
AccessHelper.ExecuteNonQuery(Config.ConnectionString, cmdText);
}
[TestMethod]
[Ignore]
public void AlterProcedureTest()
{
// first check if it exists
// delete it first
// creat store procedure
const string procedureName = "CreateStoreProcedureTest";
string cmdText = string.Format(@"CREATE PROC {0} AS SELECT * FROM t_Cow;"
, procedureName);
AccessHelper.ExecuteNonQuery(Config.ConnectionString, cmdText);

// Alter it by droping it then creating it with new implementation
cmdText = string.Format(@"Drop PROC {0};", procedureName);
AccessHelper.ExecuteNonQuery(Config.ConnectionString, cmdText);

cmdText
= string.Format(@"CREATE PROC {0} ([@ID] Short) AS SELECT * FROM t_Cow WHERE ID=[@ID];"
, procedureName);
AccessHelper.ExecuteNonQuery(Config.ConnectionString, cmdText);

// drop store procedure
cmdText = string.Format(@"Drop PROC {0};", procedureName);
AccessHelper.ExecuteNonQuery(Config.ConnectionString, cmdText);
}

//[TestMethod]
public void CheckObjectExistence()
{
//SELECT count(*) FROM MSysObjects Where Name = 'Admin'
string cmdText = string.Empty;
const string TABLE_NAME = "Tab1";
if (Exists(TABLE_NAME))
{
// drop it
cmdText = string.Format(@"Drop Table {0};", TABLE_NAME);
AccessHelper.ExecuteNonQuery(Config.ConnectionString, cmdText);
}
cmdText
= string.Format(@"Create Table {0} (
ID Counter,
Name string,
Age integer,
[Date] DateTime);
", TABLE_NAME);
AccessHelper.ExecuteNonQuery(Config.ConnectionString, cmdText);
Assert.IsTrue(Exists(TABLE_NAME));

// drop it
cmdText = string.Format(@"Drop Table {0};", TABLE_NAME);
AccessHelper.ExecuteNonQuery(Config.ConnectionString, cmdText);
Assert.IsFalse(Exists(TABLE_NAME));
}
private bool Exists(string objectName)
{
// create procedure
const string ProcedureName = "IsExists";
try
{
string cmdText = string.Format(@"Create Proc {0} ([ObjectName] text(50)) AS SELECT count(*) FROM MSysObjects Where Name = [ObjectName];", ProcedureName);
AccessHelper.ExecuteNonQuery(Config.ConnectionString, cmdText);
}
catch (Exception ex)
{
// The procedure has been created.
}

int count = int.Parse(AccessHelper.ExecuteScalar(Config.ConnectionString, ProcedureName,objectName).ToString());

if (count == 1)
return true;
else if (count == 0)
return false;
else
throw new Exception("There are multi objects existing in data base!");
}
}

How to use EventHandler in C#

  1. The EventHandler will be instantiated when there are methods having registered to it
  2. To raise the event please first check if the EventHandler is null or not
Sample:


using System;
using System.Collections.Generic;
using System.Text;
using COW.Business;

namespace COW.Hybridization
{
public interface IShortcutItem
{
event EventHandler Saving;

event EventHandler Saved;

event EventHandler Canceled;

string Content
{
get;
set;
}

int ParentID
{
get;
}

string ParentName
{
get;
}

string ItemName
{
get;
}

string ContentName
{
get;
}

void Save();

void Cancel();

bool IsValidContent(out string errorMessage);
}

public abstract class AbstractShortcutItem : IShortcutItem
{
protected string content = string.Empty;
protected int parentID = int.MaxValue;
protected string parentName = string.Empty;
protected string contentName = string.Empty;
protected string itemName = string.Empty;

public AbstractShortcutItem(
int parentID,
string parentName,
string itemName,
string contentName)
{
if (itemName == null || itemName == string.Empty
|| contentName == null || contentName == string.Empty)
throw new ArgumentNullException();

this.parentID = parentID;
this.parentName = parentName;
this.itemName = itemName;
this.contentName = contentName;
}

public abstract event EventHandler Saving;

public abstract event EventHandler Saved;

public abstract event EventHandler Canceled;

public string Content
{
get{
return content;
}
set{
content
= value;
}
}

public int ParentID
{
get { return parentID; }
}

public string ParentName
{
get { return parentName; }
}

public string ItemName
{
get { return itemName; }
}

public string ContentName
{
get { return contentName; }
}

public abstract void Save();

public abstract void Cancel();

public virtual bool IsValidContent(out string errorMessage)
{
errorMessage
= string.Empty;
if (content == null || content.Trim() == string.Empty){
errorMessage
= string.Format(Properties.Resources.PleaseInput,contentName);
return false;
}
return true;
}

}

// town
public class TownShortcutItem : AbstractShortcutItem
{
public TownShortcutItem():base(int.MaxValue,
string.Empty,
Properties.Resources.Town,
Properties.Resources.ObjectName)
{
}

public override void Save()
{
string message ;
if (!IsValidContent(out message))
throw new ArgumentException("Invalid town content!");

if(Saving != null)
Saving(
this, new EventArgs());

Town town
= new Town();
town.Name
= content;
Town.Add(town);

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

public override void Cancel()
{
// nothing
if(Canceled != null)
Canceled(
this, new EventArgs() );
}

public override bool IsValidContent(out string errorMessage)
{
if (!base.IsValidContent(out errorMessage))
return false;

if (Town.IsDuplicate(content)){
errorMessage
= Properties.Resources.NameBeingUsed;
return false;
}
return true;
}

public override event EventHandler Saving ;

public override event EventHandler Saved;

public override event EventHandler Canceled ;
}
// village
public class VillageShortcutItem : AbstractShortcutItem
{
public VillageShortcutItem(int parentID)
:
base(parentID,
Town.Get(parentID).Name,
Properties.Resources.Village,
Properties.Resources.ObjectName)
{
if (parentID == int.MaxValue)
throw new ArgumentException("Invalid parent ID!");
}

public override void Save()
{
string message;
if (!IsValidContent(out message))
throw new ArgumentException("Invalid village content!");

if(Saving != null)
Saving(
this, new EventArgs());

Village village
= new Village();
village.TownID
= parentID;
village.Name
= content;
Village.Add(village);

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

public override void Cancel()
{
if(Canceled != null)
Canceled(
this, new EventArgs());
}

public override bool IsValidContent(out string errorMessage)
{
if (!base.IsValidContent(out errorMessage))
return false;

if (Village.IsDuplicate(content, parentID)){
errorMessage
= Properties.Resources.NameBeingUsed;
return false;
}

return true;
}

public override event EventHandler Saving;

public override event EventHandler Saved;

public override event EventHandler Canceled;
}
// group
public class GroupShortcutItem : AbstractShortcutItem
{
public GroupShortcutItem(int parentID)
:
base(parentID,Village.Get(parentID).Name, Properties.Resources.Group, Properties.Resources.ObjectName)
{
if (parentID == int.MaxValue)
throw new ArgumentException("Invalid parent ID!");
}

public override void Save()
{
string message ;
if (!IsValidContent(out message))
throw new ArgumentException("Invalid group content!");

if(Saving != null)
Saving(
this, new EventArgs());

Group group
= new Group();
group.VillageID
= parentID;
group.Name
= content;
Group.Add(group);

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

public override void Cancel()
{
if(Canceled != null)
Canceled(
this, new EventArgs());
}

public override bool IsValidContent(out string errorMessage)
{
if (!base.IsValidContent(out errorMessage))
return false;

if (Group.IsDuplicate(content, parentID)){
errorMessage
= Properties.Resources.NameBeingUsed;
return false;
}

return true;
}

public override event EventHandler Saving;

public override event EventHandler Saved;

public override event EventHandler Canceled;
}
// cultivationhousehold
public class CultivationholdShortcutItem : AbstractShortcutItem
{
public CultivationholdShortcutItem(int parentID)
:
base(parentID, Group.Get(parentID).Name, Properties.Resources.CultivationHousehold, Properties.Resources.CultivationHouseholdName)
{
if (parentID == int.MaxValue)
throw new ArgumentException("Invalid parent ID!");
}

public override void Save()
{
string message;
if (!IsValidContent(out message))
throw new ArgumentException("Invalid cultivationhold name!");

if(Saving != null)
Saving(
this, new EventArgs());

CultivationHousehold household
= new CultivationHousehold();
household.GroupID
= parentID;
household.Name
= content;
CultivationHousehold.Add(household);

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

public override void Cancel()
{
if(Canceled != null)
Canceled(
this, new EventArgs());
}

public override bool IsValidContent(out string errorMessage)
{
if (!base.IsValidContent(out errorMessage))
return false;

if (CultivationHousehold.IsDuplicate(content, parentID)){
errorMessage
= Properties.Resources.NameBeingUsed;
return false;
}

return true;
}

public override event EventHandler Saving;

public override event EventHandler Saved;

public override event EventHandler Canceled;
}
// cow
public class CowShortcutItem : AbstractShortcutItem
{
public CowShortcutItem(int parentID)
:
base(parentID, CultivationHousehold.Get(parentID).Name, Properties.Resources.Cow, Properties.Resources.ObjectName)
{
if (parentID == int.MaxValue)
throw new ArgumentException("Invalid parent ID!");
}

public override void Save()
{
string message;
if (!IsValidContent(out message))
throw new ArgumentException("Invalid cow content!");

if(Saving != null)
Saving(
this, new EventArgs());

Cow cow
= new Cow();
cow.CultivationHouseholdID
= parentID;
cow.CowEarMark
= content;
Cow.Add(cow);

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

public override void Cancel()
{
if(Canceled != null)
Canceled(
this, new EventArgs());
}

public override bool IsValidContent(out string errorMessage)
{
if (!base.IsValidContent(out errorMessage))
return false;

if (Cow.IsDuplicate(Content)){
errorMessage
= Properties.Resources.CowEarMarkBeingUsed;
return false;
}

return true;
}
public override event EventHandler Saving;

public override event EventHandler Saved;

public override event EventHandler Canceled;
}
}



Sample to use the event:

private void ShortcutAddVillageLabel_Click(object sender, EventArgs e)
{
errorProvider.Clear();

if (SelectedTownID == INVALID_ID)
{
errorProvider.SetError(comboBoxTown, Properties.Resources.PleaseSelectTown);
return;
}
VillageShortcutItem village
= new VillageShortcutItem(SelectedTownID);
village.Saved
+= delegate {
BeginInvoke(
new RefreshObject(RefreshVillage));
};
using (ShortcutAdding shortcut = new ShortcutAdding(village))
{
shortcut.ShowDialog();
}
}