1 Востаннє редагувалося FakiNyan (10.11.2013 12:43:44)

Тема: Як звернутись до елементу форми з своєї dll?

Привітульки. Значить є проект ВіндовсФорм. В цьому проекті є звичайний клас, котрий призначений для працювання з контролами форми, і є клаc Server, котрий є сервером. Так от, при натисканні на кніпочку в класі форми, створюється новий об'єкт Server, цьому серверу передається посилання на цю форму, і тепер він може управляти контролами форми. Але цей сервер є асинхронним, і до контролів форми необхідно звертатись з інших потоків, для цього я використовую делегат та метод Invoke. Також є деяка dll, котра має необхідні класи, з котрими працює сервер, і в методах класів, котрі описані в dll необхідно звертатись до контролів форми. От я ніяк не можу зрозуміти, як дати знати тій dll, що існує деяка форма Form1, і що в ній є RichTextBox з іменем rtbSystemMessage. От код форми

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using GameServer.GServer;

namespace GameServer
{
    public partial class Form1 : Form
    {
        private Server server;

        public Form1()
        {
            InitializeComponent();
            statusLabel.ForeColor = Color.Red;
            statusLabel.Text = "Stoped.";
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            if (server == null)
            {
                server = new Server(int.Parse(tbPort.Text), this);
                server.Start();
                statusLabel.Text = "Running...";
                statusLabel.ForeColor = Color.GreenYellow;
            }
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            if (server.IsRunning)
            {
                server.Stop();
                statusLabel.ForeColor = Color.Red;
                statusLabel.Text = "Stoped.";
            }
        }
    }
}

От клас Server

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using MySql.Data.MySqlClient;
using SCdll;

namespace GameServer.GServer
{
    class Server
    {
        private delegate void Del();

        private int _port;
        private Socket _socket;
        private MySqlConnection _mySqlConnection;
        private string _db_connect;
        private List<Client> clients;
        private Form1 form;
        private bool serverStatus;

        public bool IsRunning
        {
            get { return serverStatus; }
            set { serverStatus = value; }
        }

        public Server(int port, Form1 form)
        {
            serverStatus = false;
            _port = port;
            _db_connect = "Database=supercourse;Data Source=localhost;User Id=root;Password=пуроль))0";
            clients=new List<Client>();
            this.form = form;
        }

        public void Start()
        {
            _socket=new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
            EndPoint _endPoint = new IPEndPoint(IPAddress.Any,_port);
            _socket.Bind(_endPoint);
            _socket.Listen((int) SocketOptionName.MaxConnections);

            _socket.BeginAccept(new AsyncCallback(AcceptCallback), _socket);
            IsRunning = true;
        }

        public void Stop()
        {
            foreach (var client in clients)
            {
                client.socket.Shutdown(SocketShutdown.Both);
                client.socket.Close();
            }
            clients.Clear();
            IsRunning = false;
        }

        private void AcceptCallback(IAsyncResult result)
        {
            try
            {
                Socket acceptSocket = (Socket)result.AsyncState;
                Client client = new Client();
                client.socket = (Socket)acceptSocket.EndAccept(result);
                lock(clients) clients.Add(client);
                AddSystemMessage("New client has been added");
                client.socket.BeginReceive(client.buffer, 0, client.buffer.Length, SocketFlags.None,
                    new AsyncCallback(ReceiveCallback), client);
                _socket.BeginAccept(new AsyncCallback(AcceptCallback), _socket);
            }
            catch (Exception e)
            {
                AddSystemMessage(e.Message);
            }
        }

        private void ReceiveCallback(IAsyncResult result)
        {
            try
            {
                Client client = (Client) result.AsyncState;
                int nBytes = client.socket.EndReceive(result);
                if (nBytes > 0)
                {
                    AddSystemMessage("Received: " + nBytes + " bytes");
                    lock (clients)
                    {
                        foreach (var client1 in clients)
                        {
                            if (client1.socket != client.socket)
                                client1.socket.Send(client.buffer, nBytes, SocketFlags.None);
                        }
                    }
                }
                client.socket.BeginReceive(client.buffer, 0, client.buffer.Length, SocketFlags.None,
                    new AsyncCallback(ReceiveCallback), client);
            }
            catch (SocketException e)
            {
                AddSystemMessage(e.Message + " ErrorCode: " + e.ErrorCode.ToString());
            }
            catch (Exception e)
            {
                AddSystemMessage(e.Message);
            }
        }
        public void AddSystemMessage(string message)
        {
            form.rtbSystemMessage.Invoke(new Del(() => form.rtbSystemMessage.AppendText(message + "\n")));
        }
    }
}

А озьдо код dll'ки

using System;
using System.IO;
using System.Net.Sockets;
using System.Text;
using System.Windows.Forms;
using MySql.Data.MySqlClient;

namespace SCdll
{
    public delegate void Del();

    public class Client
    {
        public byte[] buffer = new byte[1024];
        public Socket socket;
        public double userId;
    }

    public class Character
    {
        private readonly double char_id;
        private readonly string nick;
        private readonly float pos_x;
        private readonly float pos_y;
        private readonly float pos_z;
        private readonly double user_id;

        public Character(double userId, double charId, string nick, float posX, float posY, float posZ)
        {
            user_id = userId;
            char_id = charId;
            this.nick = nick;
            pos_x = posX;
            pos_y = posY;
            pos_z = posZ;
        }

        public double UserId
        {
            get { return user_id; }
        }

        public double CharId
        {
            get { return char_id; }
        }

        public string Nick
        {
            get { return nick; }
        }

        public float PosX
        {
            get { return pos_x; }
        }

        public float PosY
        {
            get { return pos_y; }
        }

        public float PosZ
        {
            get { return pos_z; }
        }
    }

    public interface ICommand
    {
        void Execute(Client client);
    }

    public abstract class SQLString : ICommand
    {
        protected MySqlConnection connection = new MySqlConnection();
        private string connectionString = "Database=supercourse;Data Source=localhost;User Id=root;Password=пуроль))0";

        public virtual void Execute(Client client)
        {
        }
    }

    public class Login : SQLString
    {
        private readonly string login;
        private readonly string password;
        private double cmdId;

        public Login(string login, string password)
        {
            this.login = login;
            this.password = password;
            cmdId = 0;
        }

        public override void Execute(Client client)
        {
            string request = "call SP_LogIn(" + "'" + login + "'" + "," + "'" + password + "'" + ")";
            var myCommand = new MySqlCommand(request, connection);
            int value = 0;
            try
            {
                Console.WriteLine("trying open connection to db");
                connection.Open();
                value = Int32.Parse(myCommand.ExecuteScalar().ToString());
                connection.Close();
                Console.WriteLine("value = " + value);
                Console.WriteLine("done sending req to bd. Value = " + value);
                client.userId = value;
            }
            catch (Exception e)
            {
                connection.Close();
                Console.WriteLine(e.Message);
            }
            /*bw.Write("lgn"); //Encoding.UTF8.GetBytes("lgn").CopyTo(bf, 0);
            bw.Write(value); //BitConverter.GetBytes(value).CopyTo(bf, 10);
            bw.Flush();*/
        }
    }

    public class dll
    {
        private readonly Form1 form = new Form1();

        public void AddSystemMessage(string message)
        {
            form.rtbSystemMessage.Invoke(new Del(() => form.rtbSystemMessage.AppendText(message + "\n")));
        }

        public BinaryReader createReader(Client client)
        {
            return new BinaryReader(new MemoryStream(client.buffer));
        }

        public BinaryWriter createWriter(Client client)
        {
            return new BinaryWriter(new BufferedStream(new NetworkStream(client.socket)), Encoding.UTF8);
        }
    }
}

Як бачите, метод

public void AddSystemMessage(string message)
        {
            form.rtbSystemMessage.Invoke(new Del(() => form.rtbSystemMessage.AppendText(message + "\n")));
        }

та делегат

 public delegate void Del();

описані як в dll, так і на сервері, саме цей метод необхідно винести в dll.

2

Re: Як звернутись до елементу форми з своєї dll?

Я САМИЙ МАГУЩЄСТВЄННИЙ ЧЄЛАВЄК НА ЗЄМЛЄ!!!
все вирішилось за допомогою делегатів. В класі Server є метод, котрий працює з контролами форми, класс в dll приймає деякий делегат, ну наприклад, якщо метод в класі Server приймає якусь строку і нічого не повертає, то делегат буде delegate void myDel(string s); Це записано в класі dll. Потім створюємо в класі Server екземпляр класу з dll і передаємо йому наш метод, а там вже можемо викликати його та передавати різні аргументи.
В когось якісь проблеми???

Подякували: Очі.завидющі1