venerdì 14 giugno 2013

How To: Implement Dynamic Data Provider

Dopo aver scopert dynamic.. non mi sono più fermato ( ammetto di essermi complicato la vita ) ma il risultato è molto piacevole.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DynamicDataProvider;


namespace DynamicDataProvider.Test
{
    class Program
    {
        static void Main(string[] args)
        {
          
            Entities.contactType ct = new Entities.contactType();
            ct.id = 1;
            ct.Name = "Default";
            ct.Description = "";


            DynamicDataProvider.DataProvider dp = new DataProvider("contactType");

            dp.Insert(ct);

            Entities.contact c = new Entities.contact();
            c.id = 1;
            c.Name = "Fabio";
            c.Surname = "Arosio";
            c.Since = new DateTime(1974, 2, 26);
            c.Contact_Type = ct;

            dp = new DataProvider("contact");

            dp.Insert(c);
           
        }
    }
}

Che cosa si nasconde dietro questo breve listato?
Tanto codice ma riutilizzabile all 100%
il tutto parte da questa semplice ma potente interfaccia
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DynamicDataProvider.Commons
{
    public interface IDataProvider
    {
        void Insert(dynamic item);
        void Edit(dynamic item);
        void Delete(dynamic item);
        dynamic Select();
    }
}


il cui ruolo è ... non posso svelarvi tutto subito, è necessario leggere tutto il post.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DynamicDataProvider.Commons;
using DynamicDataProvider.XMLcontext;

namespace DynamicDataProvider
{
    public class DataProvider:IDataProvider
    {

        IDataProvider current = null;

        public DataProvider(string t)
        {
            current = new contextDataProvider(t);
        }
       
        public void Insert(dynamic item)
        {
            current.Insert(item);
        }

        public void Edit(dynamic item)
        {
            current.Edit(item);
        }

        public void Delete(dynamic item)
        {
            current.Delete(item);
        }

        public dynamic Select()
        {
            return current.Select();
        }

        
    }
}

Questo è il mio dataProvider, che implementa l'interfaccia, diciamo che in tutto il progetto l'interfaccia è molto molto diffusa, sia per implementare il pattern del proxy, sia per implementare in modo omogeneo tutta la struttura.


Queste le mie entià con relative collezioni
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DynamicDataProvider.Entities
{
    public class contact
    {
        public int id { get; set; }
        public string Name { get; set; }
        public string Surname { get; set; }
        public DateTime Since { get; set; }
        public contactType Contact_Type { get; set; }
    }

    public class contacts : List<contact>
    { 
    
    }
}



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DynamicDataProvider.Entities
{
    public class contactType
    {
        public int id { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
    }

    public class contactTypes :List<contactType>
    {
    }

}



Ed ora la parte più complessa... il dataContext...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DynamicDataProvider;
using DynamicDataProvider.Commons;
using DynamicDataProvider.Entities;
using DynamicDataProvider.XMLcontext.Utils;

namespace DynamicDataProvider.XMLcontext
{
    public class contextDataProvider : IDataProvider
    {
        #region Contacts
        class contactsDP :IDataProvider
        {
            private string fName = @"\Contacts.xml";
            public contacts Contacts { get; set; }

            public contactsDP()
            {
                if (Contacts == null) { Contacts = new contacts(); }                        
            }


            public void Insert(dynamic item)
            {
                Contacts.Add(item);

                XmlHelpers.Serialize<contacts>(fName, Contacts);
            }

            public void Edit(dynamic item)
            {
                for (int i = 0; i < Contacts.Count; i++)
                {
                    if (Contacts[i].id == item.id)
                    {
                        Contacts[i] = item;
                        break;
                    }
                }

                XmlHelpers.Serialize<contacts>(fName, Contacts);
            }

            public void Delete(dynamic item)
            {
                for (int i = 0; i < Contacts.Count; i++)
                {
                    if (Contacts[i].id == item.id)
                    {
                        Contacts.RemoveAt(i);
                        break;
                    }
                }

                XmlHelpers.Serialize<contacts>(fName, Contacts);
            }

            public dynamic Select()
            {
                return XmlHelpers.Deserialize<contacts>(fName);
            }
        }
        #endregion 

        #region ContactsType
        class contactTypesDP : IDataProvider
        {
            private string fName = @"\ContactsType.xml";
            public contactTypes ContactTypes { get; set; }

            public contactTypesDP()
            {
                if (ContactTypes == null) { ContactTypes = new contactTypes(); }            
            }


            public void Insert(dynamic item)
            {
                ContactTypes.Add(item);

                XmlHelpers.Serialize<contactTypes>(fName, ContactTypes);
            }

            public void Edit(dynamic item)
            {
                for (int i = 0; i < ContactTypes.Count; i++)
                {
                    if (ContactTypes[i].id == item.id)
                    {
                        ContactTypes[i] = item;
                        break;
                    }
                }

                XmlHelpers.Serialize<contactTypes>(fName, ContactTypes);
            }

            public void Delete(dynamic item)
            {
                for (int i = 0; i < ContactTypes.Count; i++)
                {
                    if (ContactTypes[i].id == item.id)
                    {
                        ContactTypes.RemoveAt(i);
                        break;
                    }
                }

                XmlHelpers.Serialize<contactTypes>(fName, ContactTypes);
            }

            public dynamic Select()
            {
                return XmlHelpers.Deserialize<contactTypes>(fName);
            }
        }
        #endregion 


        IDataProvider cur = null;

        public contextDataProvider(string t)
        {
            if (t == "contact")
            { 
                cur = new contactsDP();
            }
            if (t =="contactType")
            {
                cur = new contactTypesDP();
            }

        }



        #region IDataProvider Members

        public void Insert(dynamic item)
        {
            cur.Insert(item);
        }

        public void Edit(dynamic item)
        {
            cur.Edit(item);
        }

        public void Delete(dynamic item)
        {
            cur.Delete(item);
        }

        public dynamic Select()
        {
            return cur.Select();
        }

        #endregion
    }
}




In breve la soluzione ha il seguente aspetto.


Devo essere onesto il codice scritto non è tanto, ma il fatto di essere riuscito a disaccoppiare i dati da chi li gestisce, dal tipo e da chi li chiama... è davvero forte
Mi ha dato una certa soddisfazione arrivare a questo piccolo risultato, e ammetto che probabilmente si più limare ancora qualcosa.
Una nota, nella cartella utils trovate la mia solita utility di serializzazione e deserializzazione. Come sempre buon divertimento

Nessun commento: