Wednesday, February 29, 2012

Deep Copy Helper


       public static T DeepCopy<T>(T obj)
        {
            if (obj == null)
                throw new ArgumentNullException("Object cannot be null");
            return (T)Process(obj);
        }

        static object Process(object obj)
        {
            if (obj == null)
                return null;
            Type type = obj.GetType();
            if (type.IsValueType || type == typeof(string))
            {
                return obj;
            }
            else if (type.IsArray)
            {
                Type elementType = Type.GetType(
                     type.FullName.Replace("[]", string.Empty));
                var array = obj as Array;
                Array copied = Array.CreateInstance(elementType, array.Length);
                for (int i = 0; i < array.Length; i++)
                {
                    copied.SetValue(Process(array.GetValue(i)), i);
                }
                return Convert.ChangeType(copied, obj.GetType());
            }
            else if (type.IsClass)
            {
                object toret = Activator.CreateInstance(obj.GetType());
                //FieldInfo[] fields = type.GetFields(BindingFlags.Public |
                //            BindingFlags.NonPublic | BindingFlags.Instance);
                FieldInfo[] fields = GetAllFields(type).ToArray();
                foreach (FieldInfo field in fields)
                {
                    object fieldValue = field.GetValue(obj);
                    if (fieldValue == null)
                        continue;
                    field.SetValue(toret, Process(fieldValue));
                }
                return toret;
            }
            else
            {
                return null;
                //throw new ArgumentException("Unknown type");
            }
        }

        public static IEnumerable<FieldInfo> GetAllFields(Type t) { 
            if (t == null)         return Enumerable.Empty<FieldInfo>();
            BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance
                | BindingFlags.DeclaredOnly; 

            return t.GetFields(flags).Union(GetAllFields(t.BaseType)); 
        } 

Note that If we restrict to Serializable then using Memory Stream can deep copy

   class Program
    {
        static void Main(string[] args)
        {
            Outside o = new Outside() { Data = new Inside() { Name = "n1", Price = 199 } };

            Outside o_sc = o.ShadowCopy;
            o_sc.Data.Name = "Changed"; // change o as well since Shadow copy reference
            Outside o_dc = o.DeepCopy;
            o_dc.Data.Name = "Reset"; // not affect o
        }
    }

    [Serializable]
    public class Outside
    {
        public Inside Data { get; set; }
        public Outside ShadowCopy { get { return  MemberwiseClone() as Outside ; } }
        public Outside DeepCopy
        {
            get
            {
                MemoryStream m = new MemoryStream();
                BinaryFormatter b = new BinaryFormatter();
                b.Serialize(m, this);
                m.Position = 0;
                return b.Deserialize(m) as Outside;
            }
        }
        
    }

    [Serializable]
    public class Inside
    {
        public string Name { get; set; }
        public double Price { get; set; }
    }

Sunday, February 19, 2012

HTML5 Canvas API


<canvas w h id="cv"/>

var ctx=document.getElementById("cv").getContext('2d');

Path Drawing:
ctx.beginPath();
ctx.moveTo(x,y);
ctx.lineTo(x1,y1);
ctx.closePath();

Fill
ctx.fillRec();
ctx.fillStyle='rgba(0,0,0,0.2)'; alpha 0.2 for black.

Mouse move vs. Touch move
cv.onMouseMove= function Draw(e) {..}
document.addEventListener('touchmove', function (e) { });

e.preventDefault(); not allow Ipad Giggle.
e.targetTouches[0].pageX;
ctx.transform (matrix+d);
cx.scale(60%);