C# Cannot resolve symbol - c#

I don't know why I'm getting this error. Seems elementary. Anyway I have a singleton class called EmailSender. The code below is short and easy. The issue is that I can't use sender in the MainWindow class. Anything I try such as sender.Send() is treated as though I've done asdafsafas.Send(). It's treated as though it's a random string of characters. Don't know why this is happening.
using System;
using System.Net.Mail;
using System.Windows.Forms;
namespace SendMail
{
public partial class MainWindow : Form
{
#region Private variables
private MailMessage msg = new MailMessage();
private EmailSender sender = EmailSender.GetInstance();
#endregion
public MainWindow()
{
InitializeComponent();
}
private MailMessage PrepareMailMessage()
{
return msg;
}
private void btnSend_Click(object sender, EventArgs e)
{
}
}
}
Here is the GetInstance method:
public static EmailSender GetInstance()
{
return _instance ?? (_instance = new EmailSender());
}

This is because of the way you have this method defined (sender is a parameter). It's finding the method argument first, not your class level variable. You can qualify this:
private void btnSend_Click(object sender, EventArgs e)
{
// sender here is the "(object sender, " paramater, so it's defined
// as system object.
// use this instead:
this.sender.Send(); // The "this" will make the class find the instance level variable instead of using the "object sender" argument
}

That's because sender is not a mail object, but rather the button that triggered the event. You need the SmtpClient to send the email:
private void btnSend_Click(object sender, EventArgs e)
{
SmtpClient client = new SmtpClient("192.0.0.1", 25); //host, port
client.Send(msg);
}
Also, the MailMessage class implements IDisposable, so you need some code to dispose of the message once you're done with it.
I created a wrapper that includes everything you need to send emails, including disposal:
/// <summary>
/// Wrapper class for the System.Net.Mail objects
/// </summary>
public class SmtpMailMessage : IDisposable
{
#region declarations
MailMessage Message;
SmtpClient SmtpMailClient;
#endregion
#region constructors
/// <summary>
/// Default constructor for the SmtpMailMessage class
/// </summary>
public SmtpMailMessage()
{
//initialize the mail message
Message = new MailMessage();
Message.Priority = MailPriority.Normal;
Message.DeliveryNotificationOptions = DeliveryNotificationOptions.OnFailure;
Message.From = new MailAddress("xxx#abc.com");
//initialize the smtp client
SmtpMailClient = new SmtpClient();
SmtpMailClient.DeliveryMethod = SmtpDeliveryMethod.Network;
SmtpMailClient.Host = "192.168.0.1";
SmtpMailClient.Port = 25;
}
/// <summary>
/// Parameterized constructor for the SmtpMailMessage class. Allows for override of the default
/// SMTP host and port number
/// </summary>
/// <param name="HostIP">The IP address of the exchange server</param>
/// <param name="PortNumber">The port number for ingoing and outgoing SMTP messages</param>
public SmtpMailMessage(string HostIP, int PortNumber) : this()
{
//override the smtp host value
SmtpMailClient.Host = HostIP;
//override the smtp port value
SmtpMailClient.Port = PortNumber;
}
#endregion
#region subject / body
/// <summary>
/// The body content of the mail message
/// </summary>
public string Body
{
get
{
return Message.Body;
}
set
{
Message.Body = value;
}
}
/// <summary>
/// the subject of the mail message
/// </summary>
public string Subject
{
get
{
return Message.Subject;
}
set
{
Message.Subject = value;
}
}
#endregion
#region mail type
/// <summary>
/// Gets or sets a value that determines whether the mail message
/// should be formatted as HTML or text
/// </summary>
public bool IsHtmlMessage
{
get
{
return Message.IsBodyHtml;
}
set
{
Message.IsBodyHtml = value;
}
}
#endregion
#region sender
/// <summary>
/// Gets or sets the from address of this message
/// </summary>
public string From
{
get
{
return Message.From.Address;
}
set
{
Message.From = new MailAddress(value);
}
}
#endregion
#region recipients
/// <summary>
/// Gets the collection of recipients
/// </summary>
public MailAddressCollection To
{
get
{
return Message.To;
}
}
/// <summary>
/// Gets the collection of CC recipients
/// </summary>
public MailAddressCollection CC
{
get
{
return Message.CC;
}
}
/// <summary>
/// Gets the collection of Bcc recipients
/// </summary>
public MailAddressCollection Bcc
{
get
{
return Message.Bcc;
}
}
#endregion
#region delivery notification
/// <summary>
/// Gets or sets the delivery notification settings for this message
/// </summary>
public DeliveryNotificationOptions DeliveryNotifications
{
get
{
return Message.DeliveryNotificationOptions;
}
set
{
Message.DeliveryNotificationOptions = value;
}
}
#endregion
#region priority
/// <summary>
/// Gets or sets the Priority of this message
/// </summary>
public MailPriority PriorityLevel
{
get
{
return Message.Priority;
}
set
{
Message.Priority = value;
}
}
#endregion
#region send methods
/// <summary>
/// Sends the message anonymously (without credentials)
/// </summary>
public void Send()
{
SmtpMailClient.Send(Message);
}
/// <summary>
/// Sends the message with authorization from a network account
/// </summary>
/// <param name="Username">The Windows username of the authorizing user</param>
/// <param name="Password">The Windows password of the authorizing user</param>
/// <param name="Domain">The domain name of the network to which the authorizing user belongs</param>
public void Send(string Username, string Password, string Domain)
{
//attach a network credential to this message using the information passed into the method
SmtpMailClient.Credentials = new NetworkCredential(Username, Password, Domain);
//send the message
SmtpMailClient.Send(Message);
}
#endregion
#region IDisposable implementation
~SmtpMailMessage()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (Message != null)
Message.Dispose();
Message = null;
SmtpMailClient = null;
}
}
#endregion
}
Implementation:
using (SmtpMailMessage mail = new SmtpMailMessage("192.168.0.1", 25))
{
//set the to address to the primary email
mail.To.Add("xxx#abc.com");
//set the message type and subject and body
mail.IsHtmlMessage = true;
mail.Subject = "Foo";
mail.Body = "Hello world!";
//send the email
mail.Send();
}

If you're doing it inside the scope of your btnSend_Click method, the parameter object sender takes precedence over the global EmailSender sender.
You should either rename your global variable, eg: EmailSender m_sender or specify exactly which sender you want: this.sender.Send()

I guess you call the sender.Send in the btnSend_Click function.
In that function is a param also called sender (object sender). Now you code is confused which one to use. So rename your private var sender.

Related

Simple TCP Chat Client Code Review and Questions

I am relatively new to programming and I took it upon myself to make a simple chat application; think AIM from back in the day. This is more of a request for a code review than a list of questions. For the most part, the application works with a few minor errors which I will highlight below. Please see the code from the project: https://github.com/N8STROMO/Basic-Chat-Tcp as well as the code listed below. Questions are embedded along the way. Thanks for any help you may be able to provide!
Here is the Server Code: Server.cs
namespace Server
{
public class Server
{
// This is the port that the server will be listening on
const int PORT = 500;
// This is where the usernames and their connections will be held
readonly Dictionary<string, ServerUserConnection> userToConnections = new Dictionary<string, ServerUserConnection>();
readonly TcpListener listener;
public static void Main()
{
// Constructor for the ChatServer
Server server = new Server();
while(true)
{
Thread.Sleep(1); // Temp to keep alive
}
}
/// <summary>
/// Listens for data from clients
/// </summary>
public Server()
{
listener = TcpListener.Create(PORT);
listener.Start();
WaitForConnections();
}
/// <summary>
/// Begins an asynchronous operation to accept an incoming connection attempt
/// </summary>
private void WaitForConnections()
{
listener.BeginAcceptTcpClient(OnConnect, null);
}
/// <summary>
/// This method is executed asynchronously
/// Connects the client to the server
/// Broadcasts the user to client to be displayed on the chatform
/// Then waits for another connection to be established
/// </summary>
/// <param name="ar"></param>
void OnConnect(IAsyncResult ar)
{
//Asynchronously accepts an incoming connection attempt and creates a new TcpClient to handle remote host communication.
TcpClient client = listener.EndAcceptTcpClient(ar);
Console.WriteLine("Connected");
ReceiveUser(client);
BroadcastUserList();
WaitForConnections();
}
/// <summary>
/// Connects a user to the server and adds them to the dictionary userToConnections
/// </summary>
/// <param name="client"></param>
public void ReceiveUser(TcpClient client)
{
ServerUserConnection connection = new ServerUserConnection(this, client); // Constructor
userToConnections.Add(connection.userName, connection);
}
/// <summary>
/// For each user that is connected append the userList to include that user
/// TODO Do not need to keep a running list of users; send the user over then throw it away
/// </summary>
void BroadcastUserList()
{
string userList = "";
foreach(var connection in userToConnections)
{
userList += $"{connection.Value.userName},";
}
SendMsgToAll(MessageType.UserList, null, userList);
}
/// <summary>
/// Pushes out messages to the connected clients
/// </summary>
/// <param name="type"></param>
/// <param name="user"></param>
/// <param name="message"></param>
public void SendMsgToAll(MessageType type, ServerUserConnection user, string message)
{
Console.WriteLine($"{user?.userName}: {message}");
foreach(var connection in userToConnections)
{
Console.WriteLine($"Sending to {connection.Value.userName}");
Utils.SendInformation(type, connection.Value.stream, message);
}
}
}
}
Here is the ServerUserConnection.cs: I am having trouble understanding how the inheritance here works and what the base keyword does.
namespace Server
{
public class ServerUserConnection : UserConnection
{
readonly Server server;
/// <summary>
/// Facilitates connection
/// </summary>
/// <param name="server"></param>
/// <param name="client"></param>
public ServerUserConnection(Server server, TcpClient client) : base(client, GetUsername(client)) // Inherits from UserConnection()
{
this.server = server;
}
private static string GetUsername(TcpClient client)
{
NetworkStream stream = client.GetStream();
if(stream.CanRead)
{
// Receives infromation from the stream, determines MessageType, and returns username
string userName = Utils.ReceiveInformation(stream, client, out MessageType type);
Console.WriteLine(userName);
return userName;
}
return null;
}
/// <summary>
///
/// </summary>
/// <param name="type"></param>
/// <param name="message"></param>
protected override void OnRead(MessageType type, string message)
{
if(type != MessageType.ChatMessage)
{
return;
}
server.SendMsgToAll(MessageType.ChatMessage, this, $"{userName} {message}");
}
}
}
Here is the Client Code: Client.cs
namespace Client
{
public class ChatClient
{
private const int PORT = 500;
TcpClient client = new TcpClient();
public ChatForm chatForm;
public ClientUserConnection userConnection;
string data;
[STAThread]
public static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var client = new ChatClient();
var form = new ConnectForm(client);
Application.Run(form);
}
/// <summary>
/// This is called when the ConnectForm btnSubmit is pressed.
/// </summary>
/// <param name="ipAddress"></param>
/// <param name="userName"></param>
public void ConnectToServer(string ipAddress, string userName)
{
client.Connect(ipAddress, PORT);
SendUserName(userName);
}
/// <summary>
/// Sends user to the server
/// </summary>
public void SendUserName(string user)
{
userConnection = new ClientUserConnection(client, this, user);
Utils.SendInformation(MessageType.Connect, client.GetStream(), user);
}
/// <summary>
/// Sends a message to the server
/// </summary>
/// <param name="msg"></param>
public void SendMessage(string msg)
{
Utils.SendInformation(MessageType.ChatMessage, userConnection.stream, msg);
}
}
}
Here is the ClientUserConnection.cs: Is there a way to refactor or optimize this so that instead of keeping a running list of messages just send the message over and throw it away? Again, the same question about inheritance.
public class ClientUserConnection : UserConnection
{
public readonly Client.ChatClient chatClient;
public string message = "";
public string userListText;
/// <summary>
///
/// </summary>
/// <param name="client"></param>
/// <param name="chatClient"></param>
/// <param name="userName"></param>
public ClientUserConnection(TcpClient client, Client.ChatClient chatClient, string userName) : base(client, userName) // Inherits from UserConnection()
{
this.chatClient = chatClient;
}
/// <summary>
/// When the data is reads determine what kind of message it is
/// Parse/split out the message and user; display only relevant data
/// TODO Do not need to keep a running list of messages; send the message over then throw it away
/// </summary>
/// <param name="type"></param>
/// <param name="message"></param>
protected override void OnRead(MessageType type, string message)
{
if(type == MessageType.ChatMessage)
{
int iSpace = message.IndexOf(" ");
if(iSpace < 0)
{
// if error
return;
}
string from = message.Substring(0, iSpace);
string chatMessage = message.Substring(iSpace + 1, message.Length - iSpace - 1);
this.message += $"[{from}]: {chatMessage}{Environment.NewLine}";
}
else if(type == MessageType.UserList)
{
string[] userList = message.Split(',');
string userListText = "";
for(int i = 0; i < userList.Length; i++)
{
userListText += $"{userList[i]}{Environment.NewLine}";
}
this.userListText = userListText;
}
}
}
There are also three files within a class library that are used within this project:
This is the MessageType.cs:
public enum MessageType
{
Connect, UserList, ChatMessage
}
This is the UserConnection.cs: I still need to deal with disconnecting users. If one of the chat forms is closed, it crashes the application.
public abstract class UserConnection
{
public readonly TcpClient client;
public readonly NetworkStream stream;
public readonly string userName;
byte[] data;
/// <summary>
///
/// </summary>
/// <param name="client"></param>
/// <param name="userName"></param>
public UserConnection(TcpClient client, string userName)
{
this.client = client;
this.userName = userName;
stream = client.GetStream();
data = new byte[client.ReceiveBufferSize];
WaitForData();
}
/// <summary>
///
/// </summary>
private void WaitForData()
{
Console.WriteLine("Wait");
stream.BeginRead(data, 0, data.Length, OnReadData, null);
}
/// <summary>
/// SocketException: An existing connection was forcibly closed by the remote host
/// </summary>
/// <param name="ar"></param>
void OnReadData(IAsyncResult ar)
{
Console.WriteLine("Read");
int result = stream.EndRead(ar); // TODO disconnect & error handling
Console.WriteLine("Read done");
if(result <= 0)
{
Console.WriteLine("Error reading");
return;
}
string message = Utils.ReceiveInformation(data, result, out MessageType type);
OnRead(type, message);
WaitForData();
}
/// <summary>
///
/// </summary>
/// <param name="type"></param>
/// <param name="message"></param>
protected abstract void OnRead(MessageType type, string message);
}
This is the Utils.cs: I am having trouble understanding how there are two methods called ReceiveInformation() and how they interact with each other
public class Utils
{
/// <summary>
///
/// </summary>
/// <param name="stream"></param>
/// <param name="connection"></param>
/// <param name="type"></param>
/// <returns></returns>
public static string ReceiveInformation(NetworkStream stream, TcpClient connection, out MessageType type)
{
byte[] bytes = new byte[connection.ReceiveBufferSize];
int length = stream.Read(bytes, 0, bytes.Length);
return ReceiveInformation(bytes, length, out type);
}
/// <summary>
///
/// </summary>
/// <param name="bytes"></param>
/// <param name="length"></param>
/// <param name="type"></param>
/// <returns></returns>
public static string ReceiveInformation(byte[] bytes, int length, out MessageType type)
{
string data = Encoding.ASCII.GetString(bytes, 0, length);
int iSpace = data.IndexOf(' ');
if(iSpace < 0)
{
// TODO
}
string typeString = data.Substring(0, iSpace);
type = (MessageType)Enum.Parse(typeof(MessageType), typeString);
string message = data.Substring(iSpace + 1, data.Length - iSpace - 1);
return message;
}
/// <summary>
///
/// </summary>
/// <param name="type"></param>
/// <param name="stream"></param>
/// <param name="message"></param>
public static void SendInformation(MessageType type, NetworkStream stream, string message)
{
Byte[] sendBytes = Encoding.UTF8.GetBytes($"{type} {message}");
stream.Write(sendBytes, 0, sendBytes.Length);
}
}

Hooking Unity Interception to a method with no parameters

I am working on a proof of concept for using Unity and I am having issues with my interceptor being called. I am using policy injection.
so here is some code
setting up unity:
private void ApplyCrossCuttingConcerns(UnityContainer container)
{
container.AddNewExtension<Interception>();
container.RegisterType<IContact, Contact>(
new InterceptionBehavior<PolicyInjectionBehavior>(),
new Interceptor<InterfaceInterceptor>());
container.Configure<Interception>()
.AddPolicy("extensionPolicy")
.AddMatchingRule<TypeMatchingRule>(new InjectionConstructor(typeof(Contact).ToString()))
.AddMatchingRule<MethodSignatureMatchingRule>(new InjectionConstructor("Save",new [] {""},true))
.AddCallHandler<ExtensionHandler>(new ContainerControlledLifetimeManager(), new InjectionConstructor());
}
my contact class that inherites from BussinessObject where the method in question lives
public class Contact : BussinessObject, IContact
{...}
public abstract class BussinessObject
{
#region Local Vars
protected readonly IRepository _repository;
protected bool isNew;
#endregion Local Vars
#region Properties
/// <summary>
/// Gets or sets a value indicating whether this instance is new.
/// </summary>
/// <value>
/// <see langword="true" /> if this instance is new; otherwise, <see langword="false" />.
/// </value>
internal bool IsNew { get { return (isNew); } set { isNew = value; } }
#endregion
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="BussinessObject"/> class.
/// </summary>
/// <param name="repository">The repository.</param>
public BussinessObject(IRepository repository)
{
if (repository.IsEmpty())
{
throw new Exception("The repository is a maditory parameter for a bussiness object");
}
_repository = repository;
}
#endregion Constructors
#region Methods
#region public
/// <summary>
/// Saves this instance.
/// </summary>
public virtual void Save()
{
Validate();
SetIdenity();
if (isNew)
{
Insert();
}
else
{
Update();
}
isNew = false;
}
/// <summary>
/// Permantlies the remove from system.
/// </summary>
/// <param name="ID">The identifier.</param>
public abstract void PermantlyRemoveFromSystem(Guid id);
#endregion public
#region Internal
/// <summary>
/// Sets the idenity.
/// </summary>
internal abstract void SetIdenity();
#endregion Internal
#region protected
/// <summary>
/// Commons the initialize.
/// </summary>
protected virtual void CommonInit()
{
isNew = false;
}
/// <summary>
/// Inserts this instance.
/// </summary>
protected abstract void Insert();
/// <summary>
/// Updates this instance.
/// </summary>
protected abstract void Update();
/// <summary>
/// Validates this instance.
/// </summary>
protected abstract void Validate();
#endregion protected
#endregion
}
Now the IContact
public interface IContact : DTO.IContact
{
void Save();
void Delete();
#region Phone Number Manipulation
bool SetDefaultNumber(PhoneNumber phNum);
PhoneNumber GetDefaultNumber();
bool HasDefaultNumber();
PhoneNumber[] GetPhoneNumbers();
PhoneNumber[] GetPhoneNumbers(bool includeDeleted);
void AddPhoneNumber(PhoneNumber phToAdd);
bool RemovePhoneNumber(PhoneNumber phToRemove);
#endregion
#region Email Address Manipulation
bool SetDefaultEMailAddress(EmailAddress emAdd);
bool HasDefaultEmailAddress();
EmailAddress[] GetAllEmailAddresses();
EmailAddress[] GetAllEmailAddresses(bool includeDeleted);
EmailAddress AddEmailAddress(string addressToAdd);
EmailAddress GetDefaultEMailAddress();
#endregion
#region Snailmail Address Manipulation
bool SetDefaultAddress(SnailMailAddress ad);
SnailMailAddress GetDefaultAddress();
bool HasDefaultAddress();
SnailMailAddress[] GetAllAddresses();
SnailMailAddress[] GetAllAddresses(bool includeDeleted);
void AddAddress(SnailMailAddress adToAdd);
bool RemoveAddress(SnailMailAddress adToRemove);
#endregion
}
and finally the extensionHandler
public class ExtensionHandler : ICallHandler
{
public int Order { get; set; }
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
//going to do our work before we pass on to the next item in the pipeline
SomeFunctionality handlerFunctionality = new SomeFunctionality();
handlerFunctionality.PreformWork();
//pass on to the next item in the pipeline
var result = getNext().Invoke(input, getNext);
//we can put post processing logic in here
return result;
}
I setup a test to resolve the contact object and then set so data on it and called the save method. I have a break point at the top of the invoke method in the ExtensionHandler but I never get there. I think the issue with the way I configuring the MethodSignatureMatchingRule but I have not yet to find documentation on the net showing an example of interception being configured to a method with no parameters.
Any help would be appreaiated
so after some more experimentation I found the answer
This issue was in the matching rules
both rules where incorrect the correct code is as follows:
private void ApplyCrossCuttingConcerns(UnityContainer container)
{
container.AddNewExtension<Interception>();
container.RegisterType<IContact, Contact>(
new InterceptionBehavior<PolicyInjectionBehavior>(),
new Interceptor<InterfaceInterceptor>());
container.Configure<Interception>()
.AddPolicy("extensionPolicy")
.AddMatchingRule<TypeMatchingRule>(new InjectionConstructor(new InjectionParameter(typeof(IContact))))
.AddMatchingRule<MemberNameMatchingRule>(new InjectionConstructor(new InjectionParameter("Save")))
.AddCallHandler<ExtensionHandler>(new ContainerControlledLifetimeManager(), new InjectionConstructor());
}

How to Mock TCPClient by implementing the interface

I am new to computer science and have few knowledge in network.
I got a task in my internship.It is to mock a TCPClient by implement Interface.
The idea is that since we don't need to connect to the real server, we just need a mock TCPClient to receive data, save it and send it out. From what I understand, is it just to mock the sendmessage function in TCPClient??
public interface ITCPClient
{
/// <summary>
/// Event handler when TCP client is connected
/// </summary>
event ConnectionEventHandler Connected;
/// <summary>
/// Event handler for TCP Client on receiving data
/// </summary>
event DataReceivedEventHandler DataReceived;
/// <summary>
/// Event handler when TCP client is disconnect
/// </summary>
event ConnectionEventHandler Disconnected;
/// <summary>
/// Reports error when an error occurs
/// </summary>
event ErrorEventHandler OnError;
/// <summary>
/// Set whether to use HostByteOrder or NetworkByteorder with the socket - gateway expects network byte order
/// </summary>
bool ByteOrder { get; set; }
/// <summary>
/// Returns true if the client is running and connected to the server
/// </summary>
bool IsRunning { get; }
/// <summary>
/// Add the message to the sendqueue. The message will be processed by the ProcessMessage function waiting for the message.
/// </summary>
/// <param name="Message"></param>
void SendMessage(string Message);
/// <summary>
/// Add the message to the sendqueue. The message willbe processed by the ProcessMessage function waiting for the message.
/// </summary>
/// <param name="Message"></param>
void SendMessageHiPriority(string Message);
/// <summary>
/// Starts the client and spawn the thread for processing the message
/// </summary>
void Start();
/// <summary>
/// Disconnects and stops listening for messages
/// </summary>
void StopProcessing();
}
public class MockTCPClient : ITCPClient
{
#region Private Fields
private string msg;
#endregion Private Fields
#region Constructor
public MockTCPClient()
{
//nothing
}
#endregion Constructor
#region event
public event ConnectionEventHandler Connected;
public event ConnectionEventHandler Disconnected;
public event ErrorEventHandler OnError;
public event DataReceivedEventHandler DataReceived;
#endregion event
#region property
//question
public string ReceivedMessage
{
get
{
return msg;
}
set
{
msg = value;
}
}
#endregion property
//question??
private void OnDataReceived(object sender, string e)
{
DataReceivedEventHandler dataReceived = DataReceived;
if (dataReceived != null)
dataReceived(this, e);
}
#region ITCPClient Members
#region properties
public bool ByteOrder { get; set; }
public bool IsRunning { get; }
#endregion properties
public void SendMessage(string Message)
{
msg = Message;
}
public void SendMessageHiPriority(string Message)
{
}
public void Start()
{
}
public void StopProcessing()
{
}
#endregion ITCPClient Members
}
This demonstrates how Moq can verify that your class calls one of its methods.
This test
- creates a mock of ITCPClient
- specifies that the SendMessage method is verifiable - in other words, its usage will be tracked.
- verifies that SendMessage("test"); has been called on the mocked object.
The test will fail because it never calls SendMessage("test");
[TestMethod]
public void TestTcpClient()
{
var mockedTcpClient = new Mock<ITCPClient>();
mockedTcpClient.Setup(x => x.SendMessage(It.IsAny<string>())).Verifiable();
//mockedTcpClient.Object.SendMessage("test");
mockedTcpClient.Verify(x=>x.SendMessage("test"));
}
If we uncomment the line that calls SendMessage("test") then the test will pass.
So in "real" usage you would create the Mock and use it in place of an ITCPClient when testing the class that depends on it. When it's done you can Verify that your class called SendMessage and passed the expected value.
If you can't use Moq, here's a totally different approach:
Create a class that implements ITCPClient as follows. You can leave most of the methods empty and just implement SendMessage along with a few other details:
public class TcpClientMock : ITCPClient
{
private readonly List<string> _sentMessages;
public TcpClientMock(List<string> sentMessages)
{
_sentMessages = sentMessages;
}
public void SendMessage(string Message)
{
_sentMessages.Add(Message);
}
//rest of non-implemented methods
}
In your unit test, do this:
var sentMessages = new List<string>();
var mockedTcpClient = new TcpClientMock(sentMessages);
Then create whatever class you're going to test and act on it. When it's done, see if sentMessages contains the message you expect.
As for receiving data, I suppose you'd need to tell your mocked object to raise that event so you could verify that your class responds as expected when the event is raised. You could add a method to TcpClientMock like this:
public void SimulateDataReceived(object sender, DataReceivedEventHandlerArgs args)
{
DataReceived(sender, args);
}
That way when you've set up your class that depends on ITCPClient you can call SimulateDataReceived on the mock, causing it to raise the event, which in turn will cause your test subject to respond.

Wpf application on .NET 4.5 to .NET 4.0

I'm in face on the following problem: An application developed on Microsoft Visual Studio 2013 in .NET 4.5, needs to work in Window XP Platforms. I'm rebuild the software using .NET 4.0 and make some modifications to add compatibility, but when i click in a button the app crash and don't show a clear error message and the Trace resource don't log anything. On application start i had a little window that ask user to put your name, and this feature works fine. Anybody have any suggestion of what can i do ?
EDIT 1:
The follow code is the root of problems, this code was compiled using .NET 4.0:
SerialManager.cs
using System;
using System.Windows;
using TestSat;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO.Ports;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Text.RegularExpressions;
using System.Diagnostics;
namespace TestSat.DataModel
{
/// <summary>
///
/// </summary>
public class SerialManager : INotifyPropertyChanged
{
#region Events
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
///
/// </summary>
/// <param name="propertyName"></param>
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
/* [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
public sealed class CallerMemberNameAttribute : Attribute
{
}*/
/// <summary>
///
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="field"></param>
/// <param name="value"></param>
/// <param name="propertyName"></param>
/// <returns></returns>
protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
field = value;
OnPropertyChanged(propertyName);
return true;
}
#endregion
#region Private Fields
private static SerialPort PortaSerial;
private ObservableCollection<String> mPorts;
private String mSelectedPort;
private int mBaudRate = 115200;
private int mDataBits = 8;
#endregion
#region Public Fields
public StringBuilder logText;
#endregion
#region Properties
/// <summary>
///
/// </summary>
public ObservableCollection<String> COMPorts
{
get { return mPorts; }
set { SetField(ref mPorts, value); }
}
/// <summary>
///
/// </summary>
public String TextoLog
{
get { return logText.ToString(); }
set
{
if (logText.Length >= logText.MaxCapacity)
{
logText.Clear();;
logText.Append(value);
}
else
{
logText.Append(value);
//MainWindow.last = value;
}
OnPropertyChanged("TextoLog");
}
}
/// <summary>
///
/// </summary>
public String SelectedPort
{
get { return mSelectedPort; }
set {SetField(ref mSelectedPort, value); }
}
#endregion
#region Construtors
/// <summary>
///
/// </summary>
public SerialManager()
{
InitComponents();
}
/// <summary>
///
/// </summary>
private void InitComponents()
{
RefreshPorts();
/*Initialize the log variable*/
logText = new StringBuilder();
/* Update selected port */
SelectedPort = COMPorts.Count > 0 ? COMPorts[0] : "";
}
#endregion
#region Public Methods
/// <summary>
///
/// </summary>
public void RefreshPorts()
{
// Update ports
string[] pPorts = SerialPort.GetPortNames();
// Sort alphabetically
Array.Sort(pPorts);
// Sort by string length
Array.Sort(pPorts, (x, y) => x.Length.CompareTo(y.Length));
// Create collection
COMPorts = new ObservableCollection<string>(pPorts);
}
/// <summary>
///
/// </summary>
/// <param name="mSelectedPort"></param>
public void ConnectSerial(String mSelectedPort)
{
PortaSerial = new SerialPort();
PortaSerial.PortName = mSelectedPort;
PortaSerial.BaudRate = mBaudRate;
PortaSerial.Parity = Parity.None;
PortaSerial.DataBits = mDataBits;
PortaSerial.StopBits = StopBits.One;
PortaSerial.Handshake = Handshake.None;
PortaSerial.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
Trace.WriteLine("DataReceived definida");
try
{
PortaSerial.Open();
}
catch (SystemException)
{
MessageBox.Show("A porta serial esta sendo usada em outra aplicação.", "Erro", MessageBoxButton.OK);
throw new SystemException();
}
}
/// <summary>
///
/// </summary>
public void DesconnectSerial()
{
if (PortaSerial.IsOpen)
{
PortaSerial.Close();
}
}
/// <summary>
///
/// </summary>
public void writeSerial(String text)
{
if (PortaSerial.IsOpen)
{
if (text.Length > 0)
{
/* char[] array = text.ToCharArray(0,text.Length);
foreach(char ch in array)
{
PortaSerial.Write(ch.ToString());
Thread.Sleep(50);
}*/
PortaSerial.WriteLine(text);
}
else
{
PortaSerial.WriteLine("");
}
}
else
{
MessageBox.Show("Porta serial não esta aberta.", "Erro", MessageBoxButton.OK);
Console.WriteLine("Porta serial não esta aberta");
}
}
/// <summary>
///
/// </summary>
public bool IsOpen()
{
return PortaSerial.IsOpen;
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
MainWindow.StartRawData = true;
SerialPort sp = (SerialPort)sender;
string indata = sp.ReadExisting();
TextoLog = indata;
/*Omited code only logical operation*/
}
#endregion
}
}
If i don't do any instance or reference to serial port the applications don't crashes. Exist a way to force this part of code compiled by .NET 3.5? Or exist another suggestion of solution for this problem?
The solution i found at http://blogs.msdn.com/b/bclteam/p/asynctargetingpackkb.asp , Issue 8. Installing the .NET 4.0 update the problems don't occured anymore.

C# 2.0 Multi-threading with a plug-in architecture

I have a well established console application in c# 2.0 that uses plugin architecture.
As of right now, the program uses basic multi-threading that can run several instances. The threads are created and continue on until the application is stopped.
Each instance can load its own variety of plugins and configured separately.
Plugins are inherited from a base plugin. This system has been working like a charm for years.
The plugins are event driven, they all read various events to see if they are called upon, if not they return and let the next plugin read the events to see if they are called out to fire.
This system has been working for years. However, I would like to further the scope of multi-threading to allow the plugins to listen to the events in an asynchronous fashion rather than synchronous. One of the drawbacks of this setup is that once a plugin fires and does its work, it locks out the instance. When the next event is fired it has to wait for the previous work to be completed. Then it will allow the next process to take place.
What I would like it to do, is execute the plugin and not have to wait for the process to end before moving on to the next process to begin by an event.
I am stuck with .Net 2.0 for the time being, and must find a solution in that framework. I have looked at numerous examples and I can not find one that meets the criteria. One of the problems is that each plugin has its own time that it may take to process, and there is no way to count to track the percentage that the plugin is complete. The plugins will start and ends its process when it is done. Depending on the parameters of the event, and the plugin it can take any range of time to complete.
My question would be what would be the best way to handle multi-threading in this situation where plugins are executed by events. I have looked at pages such as http://msdn.microsoft.com/en-us/library/2e08f6yc(v=vs.80).aspx and I can figure out where I would be able to have an entry point in an event driven plugin architecture.
If anyone has any clue, I would appreciate it. The lack of multi-threading in this manner has been the Achilles' heel for this application for years.
Plugin base: These contain some functions that are triggered by events:
using System;
using VhaBot.Communication;
namespace VhaBot
{
/// <summary>
/// Plugin BaseClass, must be inherited by all plugins
/// </summary>
public abstract class PluginBase : MarshalByRefObject
{
private bool _locked;
private string _name;
private string _internalName;
private int _version;
private string _author;
private string[] _contributors;
private string _description;
private PluginState _defaultState;
private string[] _dependencies;
private Command[] _commands;
/// <summary>
/// Friendly display name of plugin
/// </summary>
/// <example>
/// <code>
/// this.Name = "Message of the Day";
/// </code>
/// </example>
public string Name
{
set
{
if (_locked)
{
throw new Exception();
}
_name = value;
}
get { return _name; }
}
/// <summary>
/// Internal name of the plugin
/// </summary>
/// <example>
/// <code>
/// this.InternalName = "VhMotd";
/// </code>
/// </example>
public string InternalName
{
set
{
if (_locked)
{
throw new Exception();
}
_internalName = value.ToLower();
}
get { return _internalName; }
}
/// <summary>
/// Pluigin Version
/// </summary>
/// <remarks>
/// Versions are stored as integers only. Version 1.0.0 would have a value of 100
/// </remarks>
/// <example>
/// <code>
/// this.Version = 100;
/// </code>
/// </example>
public int Version
{
set
{
if (_locked)
{
throw new Exception();
}
_version = value;
}
get { return _version; }
}
/// <summary>
/// Author of the plugin
/// </summary>
/// <example>
/// <code>
/// this.Author = "Vhab";
/// </code>
/// </example>
public string Author
{
set
{
if (_locked)
{
throw new Exception();
}
_author = value;
}
get { return _author; }
}
/// <summary>
/// List of contributors to the development of the plugin.
/// </summary>
/// <example>
/// <code>
/// this.Contributors = new string[] { "Iriche", "Kilmanagh" };
/// </code>
/// </example>
public string[] Contributors
{
set
{
if (_locked)
{
throw new Exception();
}
_contributors = value;
}
get
{
if (_contributors != null)
{
return _contributors;
}
return new string[0];
}
}
/// <summary>
/// Description of the plugin
/// </summary>
/// <example>
/// <code>
/// this.Description = "Provides an interface to the user to view who is online and/or on the private channel.";
/// </code>
/// </example>
public string Description
{
set
{
if (_locked)
{
throw new Exception();
}
_description = value;
}
get { return _description; }
}
/// <summary>
/// The default <see cref="VhaBot.PluginState" /> of the plugin
/// </summary>
/// <example>
/// <code>
/// this.DefaultState = PluginState.Installed;
/// </code>
/// </example>
/// <seealso cref="VhaBot.PluginState" />
public PluginState DefaultState
{
set
{
if (_locked)
{
throw new Exception();
}
_defaultState = value;
}
get { return _defaultState; }
}
/// <summary>
/// List of other plugins that a plugin is dependent on to function
/// </summary>
/// <remarks>
/// Plugins are referred to using their internal names. See <see cref="VhaBot.PluginBase.InternalName" />
/// </remarks>
/// <example>
/// <code>
/// this.Dependencies = new string[] { "vhItems" };
/// </code>
/// </example>
public string[] Dependencies
{
set
{
if (_locked)
{
throw new Exception();
}
_dependencies = value;
}
get
{
if (_dependencies != null)
{
return _dependencies;
}
return new string[0];
}
}
public Command[] Commands
{
set
{
if (_locked)
{
throw new Exception();
}
_commands = value;
}
get
{
if (_commands != null)
{
return _commands;
}
return new Command[0];
}
}
internal void Init()
{
_locked = true;
}
/// <summary>
/// A plugin has loaded in response to <see cref="VhaBot.ShellModules.Plugins.Load" />
/// </summary>
/// <param name="bot"></param>
/// ///
/// <remarks>Code inside this method will be executed when a plugin is loading</remarks>
public virtual void OnLoad(BotShell bot)
{
}
/// <summary>
/// A plugin has unloaded in response to <see cref="VhaBot.ShellModules.Plugins.Unload" />
/// </summary>
/// <param name="bot"></param>
/// <remarks>Code inside this method will be executed when a plugin is unloading</remarks>
public virtual void OnUnload(BotShell bot)
{
}
/// <summary>
/// A plugin has installed in response to <see cref="VhaBot.ShellModules.Plugins.Install" />
/// </summary>
/// <param name="bot"></param>
public virtual void OnInstall(BotShell bot)
{
}
/// <summary>
/// A plugin as been uninstalled in response to <see cref="VhaBot.ShellModules.Plugins.Uninstall" />
/// </summary>
/// <param name="bot"></param>
public virtual void OnUninstall(BotShell bot)
{
}
/// <summary>
/// A plugin has been upgraded (Unused)
/// </summary>
/// <param name="bot"></param>
/// <param name="version"></param>
/// <remarks>This function is not active</remarks>
public virtual void OnUpgrade(BotShell bot, Int32 version)
{
}
/// <summary>
/// Response to a command
/// </summary>
/// <param name="bot"></param>
/// <param name="e"></param>
public virtual void OnCommand(BotShell bot, CommandArgs e)
{
}
/// <summary>
/// Response to an unauthorized command
/// </summary>
/// <param name="bot"></param>
/// <param name="e"></param>
public virtual void OnUnauthorizedCommand(BotShell bot, CommandArgs e)
{
}
/// <summary>
/// Response to a command help query <see cref="VhaBot.ShellModules.Commands.GetHelp." />
/// </summary>
/// <param name="bot"></param>
/// <param name="command"></param>
/// <returns></returns>
/// <remarks>Code inside this method will be executed when help is requested</remarks>
public virtual string OnHelp(BotShell bot, string command)
{
return null;
}
/// <summary>
/// Response to a custom configuration
/// </summary>
/// <param name="bot"></param>
/// <param name="key"></param>
/// <returns></returns>
public virtual string OnCustomConfiguration(BotShell bot, string key)
{
return null;
}
/// <summary>
/// Response to a plugin message
/// </summary>
/// <param name="bot"></param>
/// <param name="message"></param>
public virtual void OnPluginMessage(BotShell bot, PluginMessage message)
{
}
/// <summary>
/// Response to a bot message
/// </summary>
/// <param name="bot"></param>
/// <param name="message"></param>
public virtual void OnBotMessage(BotShell bot, BotMessage message)
{
}
/// <summary>
/// Returns display name of bot and current version
/// </summary>
/// <returns></returns>
public override string ToString()
{
return Name + " v" + Version;
}
/// <summary>
/// There is no information to document this command
/// </summary>
/// <param name="bot"></param>
/// <param name="args"></param>
public void FireOnCommand(BotShell bot, CommandArgs args)
{
try
{
if (args.Authorized)
OnCommand(bot, args);
else
OnUnauthorizedCommand(bot, args);
}
catch (Exception ex)
{
CommandArgs e = args;
var window = new RichTextWindow(bot);
window.AppendTitle("Error Report");
window.AppendHighlight("Error: ");
window.AppendNormal(ex.Message);
window.AppendLinkEnd();
window.AppendLineBreak();
window.AppendHighlight("Source: ");
window.AppendNormal(ex.Source);
window.AppendLinkEnd();
window.AppendLineBreak();
window.AppendHighlight("Target Site: ");
window.AppendNormal(ex.TargetSite.ToString());
window.AppendLinkEnd();
window.AppendLineBreak();
window.AppendHighlight("Stack Trace:");
window.AppendLineBreak();
window.AppendNormal(ex.StackTrace);
window.AppendLinkEnd();
window.AppendLineBreak();
bot.SendReply(e,
"There has been an error while executing this command »» " +
window.ToString("More Information"));
BotShell.Output("[Plugin Execution Error] " + ex);
}
}
}
}
Events Class:
namespace VhaBot.ShellModules
{
/// <summary>
/// VhaBot Events
/// </summary>
public class Events
{
public event BotStateChangedHandler BotStateChangedEvent;
public event ChannelJoinEventHandler ChannelJoinEvent;
public event UserJoinChannelHandler UserJoinChannelEvent;
public event UserLeaveChannelHandler UserLeaveChannelEvent;
public event UserLogonHandler UserLogonEvent;
public event UserLogoffHandler UserLogoffEvent;
public event PrivateMessageHandler PrivateMessageEvent;
public event PrivateChannelMessageHandler PrivateChannelMessageEvent;
public event ChannelMessageHandler ChannelMessageEvent;
public event MemberAddedHandler MemberAddedEvent;
public event MemberRemovedHandler MemberRemovedEvent;
public event MemberUpdatedHandler MemberUpdatedEvent;
public event AltAddedHandler AltAddedEvent;
public event AltRemovedHandler AltRemovedEvent;
/// <summary>
/// A message was sent to the IRC channel in response to a <see cref="VhaBot.BotShell.SendIrcMessage" /> request
/// </summary>
public event IrcMessageHandler IrcMessageEvent;
public event ConfigurationChangedHandler ConfigurationChangedEvent;
internal void OnBotStateChanged(BotShell bot, BotStateChangedArgs e)
{
if (BotStateChangedEvent != null)
try
{
BotStateChangedEvent(bot, e);
}
catch
{
}
}
internal void OnChannelJoin(BotShell bot, ChannelJoinEventArgs e)
{
if (ChannelJoinEvent != null)
try
{
ChannelJoinEvent(bot, e);
}
catch
{
}
}
internal void OnUserJoinChannel(BotShell bot, UserJoinChannelArgs e)
{
if (UserJoinChannelEvent != null)
try
{
UserJoinChannelEvent(bot, e);
}
catch
{
}
}
internal void OnUserLeaveChannel(BotShell bot, UserLeaveChannelArgs e)
{
if (UserLeaveChannelEvent != null)
try
{
UserLeaveChannelEvent(bot, e);
}
catch
{
}
}
internal void OnUserLogon(BotShell bot, UserLogonArgs e)
{
if (UserLogonEvent != null)
try
{
UserLogonEvent(bot, e);
}
catch
{
}
}
internal void OnUserLogoff(BotShell bot, UserLogoffArgs e)
{
if (UserLogoffEvent != null)
try
{
UserLogoffEvent(bot, e);
}
catch
{
}
}
internal void OnPrivateMessage(BotShell bot, PrivateMessageArgs e)
{
if (PrivateMessageEvent != null)
try
{
PrivateMessageEvent(bot, e);
}
catch
{
}
}
internal void OnPrivateChannelMessage(BotShell bot, PrivateChannelMessageArgs e)
{
if (PrivateChannelMessageEvent != null)
try
{
PrivateChannelMessageEvent(bot, e);
}
catch
{
}
}
internal void OnChannelMessage(BotShell bot, ChannelMessageArgs e)
{
if (ChannelMessageEvent != null)
try
{
ChannelMessageEvent(bot, e);
}
catch
{
}
}
internal void OnMemberAdded(BotShell bot, MemberAddedArgs e)
{
if (MemberAddedEvent != null)
try
{
MemberAddedEvent(bot, e);
}
catch
{
}
}
internal void OnMemberRemoved(BotShell bot, MemberRemovedArgs e)
{
if (MemberRemovedEvent != null)
try
{
MemberRemovedEvent(bot, e);
}
catch
{
}
}
internal void OnMemberUpdated(BotShell bot, MemberUpdatedArgs e)
{
if (MemberUpdatedEvent != null)
try
{
MemberUpdatedEvent(bot, e);
}
catch
{
}
}
internal void OnAltAdded(BotShell bot, AltAddedArgs e)
{
if (AltAddedEvent != null)
try
{
AltAddedEvent(bot, e);
}
catch
{
}
}
internal void OnAltRemoved(BotShell bot, AltRemovedArgs e)
{
if (AltRemovedEvent != null)
try
{
AltRemovedEvent(bot, e);
}
catch
{
}
}
internal void OnConfigurationChanged(BotShell bot, ConfigurationChangedArgs e)
{
if (ConfigurationChangedEvent != null)
try
{
ConfigurationChangedEvent(bot, e);
}
catch
{
}
}
internal void OnIrcMessage(BotShell bot, IrcMessageArgs e)
{
if (IrcMessageEvent != null)
{
IrcMessageEvent(bot, e);
}
try
{
}
catch
{
}
}
}
}
I've got little to go on as your description of the system is a bit vague but I'll give it a shot.
From your description it seems you have some plugin, say
interface IPlugin {
PluginResult ReadAndExecuteEvents(Events e);
// Added asynchronous methods.
IAsyncResult BeginReadAndExecuteEvents(Events e, AsyncCallback cb, Object state);
PluginResult EndReadAndExecuteEvents(IAsyncResult result);
}
with
class PluginResult
{
public Boolean Stop;
// etc.
}
also you don't seem to be using .NET events, but rather some sort of Event class/enumeration.
Your old code seems to be something like:
foreach (var eventList in ReadEvents())
foreach (var plugin in pluginList)
if (plugin.ReadAndExecuteEvents(eventList).Stop)
break;
You can make this asynchronous doing something like:
foreach (var eventList in ReadEvents())
{
// It seems this is what you want, only one event processed at a time by an "instance"? So block here until unlocked.
LockProcess();
var pluginIndex = 0;
AsyncCallback handleResult = null;
handleResult = delegate(IAsyncResult result)
{
if (pluginList[pluginIndex].EndReadAndExecuteEvents(result).Stop)
goto STOP;
pluginIndex += 1;
if (pluginIndex == pluginList.Count)
goto STOP;
Events e = (Events)result.AsyncState;
pluginList[pluginIndex].BeginReadAndExecuteEvents(e, handleResult, e);
return;
STOP:
UnlockProcess();
};
pluginList[0].BeginReadAndExecuteEvents(eventList, handleResult, eventList);
}
So in .NET 2 style you could add some BeginXxx method and in its AsyncCallback do your stuff.
Of course it is up to the actual plugin to do its multithreading/asynchronisity, say if it writes a file by using BeginWrite to a FileStream etc.
I have conveniently ignored exception handling here.
So, to make your whole application use this asynchronisity you can put this code in a BeginRunEvents method, say, following the same "APM" pattern. You can then schedule this to the threadpool if you wish.
If this is not at all what you are looking for please provide some more code examples/info.

Categories