Chào mừng đến với Diễn đàn lập trình - Cộng đồng lập trình.
Trang 1 của 3 123 CuốiCuối
Kết quả 1 đến 10 của 25
  1. #1
    Ngày tham gia
    Sep 2015
    Bài viết
    0

    Plug-In Programming - Season 1: Simple && Basic Pluggable SDK

    Hi [IMG]images/smilies/2.gif[/IMG] ,

    Sau một thời gian ngâm cứu khá lâu, hôm nay, Fox sẽ trình bày cho các bạn cách lập trình Plug-In trong C#. Hy vọng những bài

    viết về đề tài này có thể giúp các bạn có cái nhìn rộng hơn về công nghệ lập trình.

    Bài viết này xuất phát từ CỘNG ĐỒNG C VIỆT; các bạn có thể tùy ý sao chép, tham khảo; nhưng xin ghi rõ nguồn. CÁM ƠN

    SEASON 1: BASIC PLUGGABLE APPLICATION



    <font color="DarkGreen">I. GIỚI THIỆU


    Plug-In cưng là ai [IMG]images/smilies/biggrin.png[/IMG] ? Plug-In là cách lập trình viên có thể mở rộng thêm một vài chức năng của một ứng dụng nào đó, mà

    không cần phải re-compile lại toàn bộ ứng dụng; Nói cách khác lập trình viên có thể mở rộng ứng dụng mà không cần phải thao

    tác bất cứ gì vào source code nguyên thủy.

    Một số ứng dụng plug-in phổ biến hiện nay: Mozilla FireFox, Microsoft Visual Studio, SharpDevelop, ứng dụng của Fox nữa [IMG]images/smilies/biggrin.png[/IMG]…

    II. Ý TƯỞNG

    _ Thông qua bài viết của anh Zcoder87

    Kỹ thuật lập trình Plugin trong lập trình VC++ . Do không rành lắm về C++, Fox bắt đầu tìm hiểu những bài viết về Plugin trên C#.

    _ Bài viết này sẽ được chia làm nhiều kỳ (từ cách xây dựng một ứng dụng Plug-In đơn giản đến những cách mới phức tạp hơn -

    Fox hy vọng sẽ có những bạn khác cùng tham gia chia sẽ [IMG]images/smilies/smile.png[/IMG] )

    III. CODING

    1. Lên kế hoạch
    _ Xây dựng một thư viện BasicArrayProcessorSDK để làm nền plug-in cho ứng dụng.
    _ Xây dựng một chuơng trình thao tác với một mảng các số nguyên.
    _ Xây dựng 2 thư viện sẽ lf 2 default plug-ins để sắp xếp và tìm kiếm trên mảng số nguyên này.

    2. Coding
    _ Trong kỳ 1 này chúng ta sẽ xây dựng một nền plug-in theo style Interfaces, Assembly và AppDomain vì đây là cách được ưa

    dùng nhất.

    _ Hệ thống thư mục output dành cho ứng dụng

    Mã:
    + Output Folder // thư mục output của ứng dụng.
    	+ PlugIns Folder // thư mục chứa các plug-in.
    	_ HostApplication.exe // file chạy chương trình chính.
    	_ PluggableLibrary.dll // thư viện tạo nền plug-in.
    a. BasicArrayProcessorSDK
    _ Mở C# IDE của bạn lên, tạo một Project Class Library, đặt tên tùy ý... (ở đây Fox đặt tên là BasicArrayProcessorSDK). Chỉnh

    đường dẫn output theo hệ thống thư mục.
    _ Chúng ta sẽ xây dựng 2 Interface, một Interface để sau này nếu ứng dụng của bạn cần một chức năng nào khác để thao tác

    với một mảng số nguyên thì chỉ cần implements Interface này.


    Mã:
    using System; namespace BasicArrayProcessorSDK{    /// <summary>    /// Interface to build an Array-Processor plug-in.    /// </summary>    public interface IArrayProcessor    {        /// <summary>        /// Do what you want to an integer array.        /// </summary>        ///         /// <param name="array">given integer array.</param>        ///         /// <returns>an integer array after having some fun.</returns>        int[] Process(int[] array);         /// <summary>        /// Chooses a manager.        /// </summary>        ///         /// <param name="host">an object to manage this plug-in.</param>        void Initialize(IHostProcessor host);         /// <summary>        /// Releases all resources.        /// </summary>        void Dispose();         /// <summary>        /// Gets or sets plug-in attributes.        /// </summary>        ArrayProcessorPlugInAttribute Attributes        {            get;            set;        }    }}
    _ Một Interface khác tượng trưng cho một host quản lý việc thực thi các plug-in(s).


    Mã:
    using System; namespace BasicArrayProcessorSDK{    /// <summary>    /// Interface to build a plug-in manager.    /// </summary>    public interface IHostProcessor    {        /// <summary>        /// Report to client a message.        /// </summary>        ///         /// <param name="message">sending message.</param>        void Report(string message);         /// <summary>        /// Releases all resources.        /// </summary>        void Dispose();    }}
    Để có thể đảm bảo rằng host sẽ load đúng những plug-in(s) hợp lệ, chúng ta cần một Attribute để đánh dấu đồng thời cũng

    quản lý những thông tin liên quan đến mỗi plug-in.


    Mã:
    using System; namespace BasicArrayProcessorSDK{    /// <summary>    /// Object represents a plug-in's attributes.    /// </summary>    [AttributeUsage(AttributeTargets.Class)]    public class ArrayProcessorPlugInAttribute : Attribute    {        #region - field(s) -         /// <summary>        /// Name of plug-in.        /// </summary>        string mName;         /// <summary>        /// publisher of plug-in.        /// </summary>        string mPublisher;         /// <summary>        /// Description of plug-in.        /// </summary>        string mDescription;         /// <summary>        /// Version of plug-in.        /// </summary>        string mVersion;         #endregion         #region - constructor(s) -         /// <summary>        /// Initialize a plug-in attribute with given name, publisher, description and version.        /// </summary>        ///         /// <param name="name">given name.</param>        /// <param name="publisher">given publisher.</param>        /// <param name="description">given description.</param>        /// <param name="version">given version.</param>        public ArrayProcessorPlugInAttribute(string name, string publisher, string description, string version)        {            mName = name;            mPublisher = publisher;            mDescription = description;            mVersion = version;        }         #endregion         #region - property(ies) -         /// <summary>        /// Gets the name of plug-in;        /// </summary>        public string Name        {            get { return mName; }        }         /// <summary>        /// Gets the publisher of plug-in;        /// </summary>        public string Publisher        {            get { return mPublisher; }        }         /// <summary>        /// Gets the description of plug-in;        /// </summary>        public string Description        {            get { return mDescription; }        }         /// <summary>        /// Gets the version of plug-in;        /// </summary>        public string Version        {            get { return mVersion; }        }         #endregion         #region - method(s) -         public override string ToString()        {            return "Name: " + mName + "; Publisher: " + mPublisher + "; Description: " + mDescription + "; Version: " + mVersion  + ".";        }         #endregion    }}
    b. Xây dựng một ứng dụng đảm đưong trách nhiệm là một host quản lý plug-in.
    _ Tạo mới một Project Windows Application trong cùng Solution (Fox đặt tên là HostViewer). Project này sẽ được Add

    References đến thư viện nền plug-in là BasicArrayProcessorSDK.dll; Các bạn chọn thuộc tính Copy Local cho thư viện

    BasicArrayProcessorSDK.dll thành false, vì chúng ta đã set output path cho thư viện này ở phần "a" rồi. Chúng ta cũng không

    quên set output path cho ứng dụng host này theo hệ thống thư mục.

    _ Chúng ta tạo một đối tượng implements từ IHostProcessor có nhiệm vụ quản lý các plug-in(s)


    Mã:
    using System;using System.Collections;using System.Collections.Generic;using System.IO;using System.Reflection;using System.Windows.Forms; using BasicArrayProcessorSDK; namespace HostViewer{    /// <summary>    /// Object represents a plug-in manager.    /// </summary>    public class HostService : IHostProcessor    {        #region - field(s) -         /// <summary>        /// Initialize a collection to store all available plug-in.        /// </summary>        private Types.ArrayProcessorCollection mPlugInCollection = new Types.ArrayProcessorCollection();         /// <summary>        /// Control to display message from this host.        /// </summary>        private Label mLabel;         #endregion         #region - constructor(s) -         /// <summary>        /// Initialize this host with a message-sender.        /// </summary>        ///         /// <param name="control">host's message-sender.</param>        public HostService(Label control)        {            mLabel = control;        }         #endregion         #region - method(s) -             #region - public member(s) -                        /// <summary>            /// Finds all library(ies) in the plug-in folder.            /// </summary>            ///             /// <param name="folderPath">folder contains all plug-in library.</param>            public void FindPlugIns(string folderPath)            {                mPlugInCollection.Clear(); // reloads them all.                 // goes through all library-file(s) in the plug-in folder...                DirectoryInfo container = new DirectoryInfo(folderPath);                 foreach (FileInfo file in container.GetFiles("*.dll"))                    this.LoadPlugIns(file.FullName);            }             /// <summary>            /// Loads available plug-in(s) to this host.            /// </summary>            ///             /// <param name="filePath">path of plug-in library.</param>            private void LoadPlugIns(string filePath)            {                Assembly pluginAssembly = Assembly.LoadFrom(filePath);                 object[] pluginAttributes;                 // loops through all the Types found in the assembly...                foreach (Type pluginType in pluginAssembly.GetTypes())                {                    pluginAttributes = pluginType.GetCustomAttributes(typeof(ArrayProcessorPlugInAttribute), true);                     // only looks for a public, non-abstract and having attribute type(s).                    if (pluginType.IsPublic && !pluginType.IsAbstract && pluginAttributes.Length != 0)                    {                        Type interfaceType = pluginType.GetInterface("BasicArrayProcessorSDK.IArrayProcessor", true);                        if (null != interfaceType) // gets the right interface-type.                        {                            Types.AvailableArrayProcessor plugin = new Types.AvailableArrayProcessor();                            plugin.AssemblyPath = filePath;                            plugin.Instance =  (IArrayProcessor)Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString()));                            plugin.Instance.Attributes = pluginAttributes[0] as ArrayProcessorPlugInAttribute;                            plugin.Instance.Initialize(this);                             mPlugInCollection.Add(plugin); // loaded done.                             plugin = null; // clean up...                        }                         interfaceType = null; // clean up...                    }                }                 pluginAssembly = null; // clean up...            }             #endregion             #region - implements IHostProcessor member(s) -             public void Report(string message)            {                mLabel.Text = message;            }             public void Dispose()            {                foreach (Types.AvailableArrayProcessor plugin in mPlugInCollection)                {                    plugin.Instance.Dispose();                    plugin.Instance = null;                }                 mPlugInCollection.Clear();            }             #endregion         #endregion         #region - property(ies) -         /// <summary>        /// Gets the plug-in collection.        /// </summary>        public Types.ArrayProcessorCollection PlugIns        {            get { return mPlugInCollection; }        }         #endregion    }     namespace Types    {        /// <summary>        /// Represents a plug-in collection.        /// </summary>        public class ArrayProcessorCollection : CollectionBase        {            #region - method(s) -             /// <summary>            /// Adds new plug-in to the collection.            /// </summary>            ///             /// <param name="plugin">new plug-in.</param>            public void Add(AvailableArrayProcessor plugin)            {                this.List.Add(plugin);            }             /// <summary>            /// Removes a plug-in from collection.            /// </summary>            ///             /// <param name="plugin">removing plug-in.</param>            public void Remove(AvailableArrayProcessor plugin)            {                this.List.Remove(plugin);            }             /// <summary>            /// Removes all plug-in from collection.            /// </summary>            public void Clear()            {                this.List.Clear();            }             #endregion             #region - property(ies) -             /// <summary>            /// Gets numbre of available plug-in(s).            /// </summary>            public int PlugInCounter            {                get { return base.List.Count; }            }             #endregion        }         /// <summary>        /// Represents an available plug-in.        /// </summary>        public class AvailableArrayProcessor        {            #region - field(s) -             /// <summary>            /// Plug-in instance.            /// </summary>            private IArrayProcessor mInstance;             /// <summary>            /// Assembly-path of plug-in.            /// </summary>            private string mAssemblyPath;             #endregion             #region - constructor(s) -             /// <summary>            /// Initialize a default instance.            /// </summary>            public AvailableArrayProcessor()                : this(null, "")            { }             /// <summary>            /// Initialize a instance with given value.            /// </summary>            ///             /// <param name="plugin">instance of a plug-in.</param>            /// <param name="path">the path of plug-in assembly.</param>            public AvailableArrayProcessor(IArrayProcessor plugin, string path)            {                mInstance = plugin;                 mAssemblyPath = path;            }             #endregion             #region - property(ies) -             /// <summary>            /// Gets, sets the instance of plug-in.            /// </summary>            public IArrayProcessor Instance            {                get { return mInstance; }                set { mInstance = value; }            }             /// <summary>            /// Gets, sets the path of plug-in assembly.            /// </summary>            public string AssemblyPath            {                get { return mAssemblyPath; }                set { mAssemblyPath = value; }            }             #endregion             #region - method(s) -             public override int GetHashCode()            {                int hashcode = 0;                 unchecked                {                    hashcode += 1000034 * mInstance.GetHashCode();                }                 return hashcode;            }             public override bool Equals(object other)            {                if (null == other) return false;                 AvailableArrayProcessor anotherOne = other as AvailableArrayProcessor;                                return this.mInstance.Equals(anotherOne.mInstance);            }             public override string ToString()            {                return mInstance.ToString();            }             #endregion        }    }}
    Sau khi đã chuẩn bị nền móng đầy đủ, chúng ta sẽ xây dựng một FormMain để chạy chương trình.

    Trong MainForm này chúng ta sẽ khai báo đối tượng HostService vừa tạo ở trên và sẽ cấp vùng nhớ new cho host này cùng với MainForm.


    Mã:
    .../// <summary>/// Adapter the host uses to talk back to this./// </summary>private HostService mHostAdapter;...
    Khai báo một mảng số nguyên Random khoãng 10 phần từ để các plug-in có chỗ mà làm việc [IMG]images/smilies/biggrin.png[/IMG]


    Mã:
    .../// <summary>/// Array to process./// </summary>private int[] mArray = new int[10];...
    Đăng ký sự kiện FormLoad cho MainForm để load các plug-in thao tác với mảng (các plug-in sẽ được load dưới dạng các button;

    khi click các button sẽ làm việc với mãng ngẫu nhiên đã tạo với chức năng riêng của mỗi plug-in).


    Mã:
    /// <summary>/// Loads all available plug-in(s) and disguises them as a <c>Button</c>./// </summary>private void MainFormOnLoad(object sender, EventArgs e){      mHostAdapter.FindPlugIns(Application.StartupPath + @"\PlugIns");       foreach (Types.AvailableArrayProcessor plugin in mHostAdapter.PlugIns)      {             // disguising...             Button button = new Button();             button.Text = plugin.Instance.Attributes.Name;             button.Tag = plugin;             button.Padding = new Padding(6, 6, 6, 6);             button.Width = pluginsFlowLayoutPanel.Width - 10;             button.Height = pluginsFlowLayoutPanel.Height / 5;             button.TextAlign = ContentAlignment.MiddleCenter;             button.Click += new EventHandler(ArrayProcessorsPicking); // registers a click event...              this.mainToolTip.SetToolTip(button, plugin.Instance.Attributes.Description);              pluginsFlowLayoutPanel.Controls.Add(button);      }       mHostAdapter.Report(mHostAdapter.PlugIns.Count + " Plug-In(s) Loaded."); // reports to clients...}
    Sự kiện click trên các plug-in button(s)


    Mã:
    /// <summary>/// Clicking on a plug-in button will process the array by the way the plug-in is for./// </summary>private void ArrayProcessorsPicking(object sender, EventArgs e){      resultFlowLayoutPanel.Controls.Clear();       Label elementResult = null;       Types.AvailableArrayProcessor processor = ((Button)sender).Tag as Types.AvailableArrayProcessor;       int[] result = processor.Instance.Process(mArray); // processing...       for (int i = 0; i < result.Length; i++)      {            elementResult = new Label();             resultFlowLayoutPanel.Controls.Add(elementResult);             this.StyleLabel(elementResult, Color.Red, result[i].ToString());      }       processor = null; // release plugin...}
    Chúng ta cũng nên đăng ký sự kiện FormClosing để có thể release những Resource có thể làm leak memory... [IMG]images/smilies/biggrin.png[/IMG]


    Mã:
    /// <summary>/// When application is about to close, release the host's resources./// </summary>private void MainFormOnClosing(object sender, FormClosingEventArgs e){      mHostAdapter.Dispose();}
    c. Xây dựng các plug-in(s)
    _ Để xây dựng một plug-in chúng ta chỉ cần tạo từng Project Class Library, Add Reference đến BasicArrayProcessorSDK.dll

    (BasicArrayProcessorSDK.dll này sẽ được set CopyLocal = false). Nhớ set ouput path cho plug-in theo "Hệ thống thư mục" nhé [IMG]images/smilies/smile.png[/IMG]

    _ Mỗi một đối tượng được tạo trong Plug-In Library chỉ cần implements đến IArrayProcessor là có thể trở thành một Plug-In để

    Host có thể load lên MainForm (dưới dạng một button).

    Chúng ta sẽ trở lại thời "cấu trúc dữ liệu và giải thuật" để xây dựng các plug-in sắp xếp và tìm kiếm nhé [IMG]images/smilies/biggrin.png[/IMG] .

    + Plug-in sắp xếp
    Ở đây Fox dùng thuật toán InsertionSort [IMG]images/smilies/biggrin.png[/IMG]


    Mã:
    using System; using BasicArrayProcessorSDK; namespace ArraySorting{    [ArrayProcessorPlugIn("Ascending Insertion Sort Plug-In", "O'Wicked Fox", "Sorting an integer array with ascending     insertion-sort style", "1.0.0")] // Khai báo Attribute để Host nhận ra các thông tin của Plug-in, các plug-in xài giấy tờ giả là không được load đâu :D    public class InsertionSortAscending : IArrayProcessor    {        private IHostProcessor mHostViewer;         private ArrayProcessorPlugInAttribute mAttributes;         #region IArrayProcessor Members         public int[] Process(int[] array)        {            // Sắp xếp InsertionSort theo thứ tự tăng dần                int k, postition, temp;             for (k = 1; k < array.Length; k++)            {                temp = array[k];                 postition = k;                while ((postition > 0) && (array[postition - 1] > temp))                {                    array[postition] = array[postition - 1];                     postition--;                }                 array[postition] = temp;            }             mHostViewer.Report("Ascending Array Sorted.");             return ArrayUtils.CopyArray(array);        }         public void Initialize(IHostProcessor host)        {            mHostViewer = host;        }         public void Dispose()        {            mAttributes = null;        }         public ArrayProcessorPlugInAttribute Attributes        {            get { return mAttributes; }            set { mAttributes = value; }        }         #endregion    }
    + Để tìm kiếm, Fox sẽ dùng cách kiểm tra trong mãng ngẫu nhiên có số nào là số nguyên tố hay không...


    Mã:
    using System;using System.Collections.Generic; using BasicArrayProcessorSDK; namespace PrimeNumberFinder{    [ArrayProcessorPlugIn("Prime-Number Finder Plug-In", "O'Wicked Fox", "Looking through a given integer array and collects all element(s) which has value a prime-number.", "1.0.0")]    public class PrimeNumberProcessor : IArrayProcessor    {        #region - field(s) -         IHostProcessor mHostSideAdapter;         private ArrayProcessorPlugInAttribute mAttributes;         #endregion         #region IArrayProcessor Members         public int[] Process(int[] array)        {            List<int> storage = new List<int>();             bool flag;             for (int i = 0; i < array.Length; i++)            {                flag = this.CheckPrimeNumber(array[i]);                if (flag)                    storage.Add(array[i]);            }             int count = storage.Count;            if (count == 0)            {                mHostSideAdapter.Report("No Prime Number Found.");                 return array;            }            else            {                mHostSideAdapter.Report(count.ToString() + " Prime-Number(s) Found.");                 int[] result = new int[count];                 storage.CopyTo(result);                 return result;            }        }         public void Initialize(IHostProcessor host)        {            mHostSideAdapter = host;        }         public void Dispose()        {            mAttributes = null;        }         public ArrayProcessorPlugInAttribute Attributes        {            get { return mAttributes; }            set { mAttributes = value; }        }         #endregion         private bool CheckPrimeNumber(int input)        {            if (input == 2) return true;             bool result = false;             int count = 0;             for (int j = 1; j <= input; j++)            {                if (input % j == 0)                {                    count++;                     if (count > 2) // số có nhìu hơn 2 thừa số nguyên tố thì không phải là số nguyên tố                    {                        result = false;                        break;                    }                    else                        result = true;                }            }             return result;        }    }}
    Nhấn Build nào [IMG]images/smilies/biggrin.png[/IMG] , sau khi build, các bạn mở thư mục output ra, nếu nó có cấu trúc sau là đúng chuẩn [IMG]images/smilies/smile.png[/IMG]


    Vậy là xong rồi [IMG]images/smilies/biggrin.png[/IMG] . Nếu sau này các bạn muốn tạo một vài plug-in để chương trình có những tính năng mới, chỉ cần thực hiện
    theo cách tạo plug-in của Fox, biên dịch plug-in ra file dll; copy vào thư mục "Plugins" của ứng dụng; restart ứng dụng thì chúng ta sẽ có một nút plug-in mới với chức năng do chúng ta tự tạo. [IMG]images/smilies/smile.png[/IMG]

    IV. KẾT

    Kỳ 1 đã hết, Để đảm bảo các bạn có thể hiểu được chút ít về bài viết của Fox, Fox sẽ yêu cầu một bài tập sau cho các bạn [IMG]images/smilies/biggrin.png[/IMG] :
    Viết một plug-in để sắp xếp các phần tử trong mảng số tự nhiên theo thuật toán BubbleSort hoặc MergeSort.

    Fox có yêu cầu thế này, nếu các bạn muốn viết bài hồi đáp sau bài hướng dẫn của Fox (Đặt câu hỏi hoặc góp ý kiến thì Fox rất hoan nghênh [IMG]images/smilies/smile.png[/IMG] ), xin các bạn hãy đính kèm theo một file .ZIP bài tập đã làm, hoặc gửi mail tới địa chỉ mail owickedfox@gmail.com.

    Mời các bạn download sourcecode cho kỳ 1 và đón xem kỳ 2 về lập trình plug-in trên một ứng dụng MDI [IMG]images/smilies/smile.png[/IMG]

    Tạm biệt [IMG]images/smilies/smile.png[/IMG]

    V. VERSION

    1. Ngày 06 tháng 04
    _ Viết bài kỳ 1.

    2. Ngày 07 tháng 04
    _ Fix hàm LoadPlugIns(), check nếu mảng attribute lấy được có chiều dài khác = 0 khi đó plug-in hợp lệ mới cho load. (check = null chương trình sẽ báo lỗi Null Exception).</font>

  2. #2
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Bài viết hay lắm đó.

    - Ở C++ khi mình muốn call 1 phương thức trên 1 file DLL/EXE thì bắc buộc phải export functions đó ra. Lấy con trỏ hàm và call nó.
    - Nhưng ở C# dù lâu quá chưa code, giờ đọc lại code hơi mệt nhưng vẫn nhận ra đối tượng Assembly. Công nhận nó hay thật. Có thể call 1 function trên DLL khá tiện lợi. (plugin thì ko bao giờ add references rồi [IMG]images/smilies/biggrin.png[/IMG] và nó là giải pháp thay thế hay)


    Mã:
    /// <summary>/// Loads available plug-in(s) to this host./// </summary>////// <param name="filePath">path of plug-in library.</param> private void LoadPlugIns(string filePath){         Assembly pluginAssembly = Assembly.LoadFrom(filePath);          object[] pluginAttributes;          // loops through all the Types found in the assembly...         foreach (Type pluginType in pluginAssembly.GetTypes())         {                    pluginAttributes = pluginType.GetCustomAttributes(typeof(ArrayProcessorPlugInAttribute), true);                   // only looks for a public, non-abstract and having attribute type(s).                  if (pluginType.IsPublic && !pluginType.IsAbstract && pluginAttributes.Length != 0)                  {                           Type interfaceType = pluginType.GetInterface("BasicArrayProcessorSDK.IArrayProcessor", true);                           if (null != interfaceType) // gets the right interface-type.                           {                                    Types.AvailableArrayProcessor plugin = new Types.AvailableArrayProcessor();                                    plugin.AssemblyPath = filePath;                                    plugin.Instance = (IArrayProcessor)Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString()));                                    plugin.Instance.Attributes = pluginAttributes[0] as ArrayProcessorPlugInAttribute;                                    plugin.Instance.Initialize(this);                                     mPlugInCollection.Add(plugin); // loaded done.                                     plugin = null; // clean up...                           }                            interfaceType = null; // clean up...                  }         }          pluginAssembly = null; // clean up...}
    Thank fox nhé!

  3. #3
    Hi anh ZCoder87,
    Cám ơn anh đã góp ý cho bài viết của em. Xem ra bài này ế quá rồi, may có anh kéo nó lại bờ [IMG]images/smilies/biggrin.png[/IMG] . Mà cũng hên, không biết ai gắn cho nó cái neo ngay đầu Box luôn nhỉ :-? .

    PS: Em sẽ cảm kích hơn, nếu anh ZCoder87 làm bài tập và cõ vài hình mình họa [IMG]images/smilies/biggrin.png[/IMG]

  4. #4
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    bài viết này cũng hay đó. Mới nghiên cứu ra (cũng làm trong C# luôn).
    Hơi khác một tí nhưng cũng dùng đối tượng Assembly luôn.
    Chức năng mới thêm vào (cả form và các xử lý đều nằm trong 1 file DLL luôn)

    http://rapidshare.com/files/231042702/menu_plugin.rar

  5. #5
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Khổ nổi em chỉ rành mỗi dotNET, Java thôi , việc tìm hiểu vấn đề của anh Huy chắc phải cần thời gian lâu dài. À hay thử với Java được không ta :-?

  6. #6
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    Lúc trước huynguyen nghĩ rằng plugin được viết trên dotNet mà load ở trên C++, VB hay Delphi là điều không thể nhưng nay thì đã biết giải pháp.
    Ở đây huynguyen ví dụ bằng code trực tiếp chứ ko tạo project.
    Đầu tiên là file AssemblyInfo.cs:

    Mã:
    using System.Reflection;using System.Runtime.CompilerServices;using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information// associated with an assembly.[assembly: AssemblyTitle("dotNETPlugin")][assembly: AssemblyDescription("")][assembly: AssemblyConfiguration("")][assembly: AssemblyCompany("Kobekara")][assembly: AssemblyProduct("dotNETPlugin")][assembly: AssemblyCopyright("Copyright © Kobekara 2009")][assembly: AssemblyTrademark("")][assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components.  If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type.[assembly: ComVisible(true)] // The following GUID is for the ID of the typelib if this project is exposed to COM[assembly: Guid("8656e98c-a589-417f-b478-14df2084ebcc")] // Version information for an assembly consists of the following four values:////      Major Version//      Minor Version //      Build Number//      Revision//// You can specify all the values or you can default the Revision and Build Numbers // by using the '*' as shown below:[assembly: AssemblyVersion("1.0.0.0")][assembly: AssemblyFileVersion("1.0.0.0")]
    Chú ý dòng màu đỏ, đây là dòng khai báo cho biết có thể build dll này ra dạng COM object.
    Tiếp theo là lớp nền:

    Mã:
    //using System;//using System.Collections.Generic;//using System.Text; public interface IMyDotNetPlugin{    #region ----- Plugin Information -----    string GetName();    string GetVersion();    string GetCompany();    string GetAuthor();    string GetDescription();    #endregion     #region ----- Communication with app. -----    void SendMessage();    void ReceiveMessage();    #endregion     #region ----- Main -----    void Init(int ParentHandle, int MyMessage);            //void ShowPlugin(HostApplication: TApplication; ParentControl: TWinControl);    //function GetPlugin: TComponent;    #endregion}
    Cuối cùng là lớp triển khai:

    Mã:
    using System;using System.Runtime.InteropServices;using System.Windows.Forms;using System.Drawing; [ClassInterface(ClassInterfaceType.AutoDual)]public class MyDotNetPlugin : IMyDotNetPlugin{    const string CS_NAME            = "My Plugin"; // your plugin name    const string CS_VERSION         = "1.001"; // your current version    const string CS_COMPANY         = "Kobekara"; // your company    const string CS_AUTHOR          = "Nguyen Trong Huy"; // your name    const string CS_DESCRIPTION     = "This is my first test plugin"; // your description     #region ----- Properties -----    private UserControl _plugin;    public UserControl myPlugin    {        get { return _plugin; }        set { _plugin = value; }    }    #endregion     [DllImport("user32.dll", EntryPoint = "SetParent")]    private static extern IntPtr SetParent(IntPtr child, IntPtr newParent);     #region ----- Plugin Information -----    public string GetName()    {        return CS_NAME;    }    public string GetVersion()    {        return CS_VERSION;    }    public string GetCompany()    {        return CS_COMPANY;    }    public string GetAuthor()    {        return CS_AUTHOR;    }    public string GetDescription()    {        return CS_DESCRIPTION;    }    #endregion     #region ----- Communication with app. -----    public void SendMessage()    {    }    public void ReceiveMessage()    {    }    #endregion     #region ----- Main -----    public void Init(int ParentHandle, int MyMessage)    {        myPlugin = new UserControl();        myPlugin.Top = 0;        myPlugin.Left = 0;        myPlugin.Width = 256;        myPlugin.Height = 256;        myPlugin.BorderStyle = BorderStyle.FixedSingle;        Panel p = new Panel();        p.Dock = DockStyle.Fill;        p.BackColor = Color.Blue;        myPlugin.Controls.Add(p);        IntPtr hwndParentPtr = new IntPtr(ParentHandle);        SetParent(myPlugin.Handle, hwndParentPtr);    }    //void ShowPlugin(HostApplication: TApplication; ParentControl: TWinControl);    //function GetPlugin: TComponent;    #endregion}
    Sau đó tạo file build.bat như sau:
    Mã:
    c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\csc.exe /t:library /out:dotNETPlugin.dll *.cs
    c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727
    egasm dotNETPlugin.dll codebase /tlb
    
    @pause
    Cuối cùng là thành quả: ta sẽ có 1 file dll và 1 file tlb tương ứng. File tlb này sẽ được import vào các project được viết trên Delphi, VB, C++ để sử dụng.

  7. #7
    import dạng type library trong delphi, trong c++ và vb hình như cũng là add reference. bạn có thể tìm hiểu thêm đối tượng com và file tlb. sau khi tìm hiểu thì có thể post lên cho mọi người tham khảo thêm.

  8. #8
    Mình cũng xây dựng một hệ thống nền chung để phát triển các ứng dụng quản lý cũng dựa theo những tác dụng gần thế này và có thể hơn thế, các bạn xem qua ứng dụng của nó ở một phần mêm nhỏ minh gửi kèm (show hướng dẫn tí thôi xem cho vui [IMG]images/smilies/11.gif[/IMG] )

  9. #9
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    @vinaghost:
    _ Document này thuộc bản quyền của bạn à? Theo mình thấy thì nó của PSoft! Mình chỉ xin góp ý kiến rằng nên hạn chế công khai tài liệu của một công ty lên mạng kẻo vi phạm bản quyền thì không hay...
    _ Project này rất là đồ sộ, nhưng trong document mình không đọc thấy hướng dẫn về cách lập trình plug-in của cậu? Nếu có thể xin bạn vui lòng cho mình xem hình về cấu trúc của Folder trương chình sau khi cài đặt được không?
    _ "Phần mềm nhỏ" hay "ứng dụng gửi kèm" của bạn nói, mình tải về không thấy (chỉ có tài liệu thiết kế thôi)!
    _ Xem cho vui thì xem truyện tranh hay hơn bạn! Bạn hiểu ý mình chứ!

    Cheer [IMG]images/smilies/biggrin.png[/IMG]

  10. #10
    Ngày tham gia
    Sep 2015
    Bài viết
    0
    hix, các bạn chỉ húp mình để học tốt c++ mình nên bắt đầu học từ đâu vậy:L

 

 
Trang 1 của 3 123 CuốiCuối

Quyền viết bài

  • Bạn Không thể gửi Chủ đề mới
  • Bạn Không thể Gửi trả lời
  • Bạn Không thể Gửi file đính kèm
  • Bạn Không thể Sửa bài viết của mình
  •