Showing posts with label C#. Show all posts
Showing posts with label C#. Show all posts

Monday, June 17, 2013

MVC: Intellisense for custom HtmlHelpers or if you want to avoid @using to import namespaces

If you write custom HtmlHelpers its quite tedious to have to add @using your.namespace.to.your.htmlHelpers on top of each page. To be able to use your newly written htmlhelpers

to avoid this just find the web.config in your views folder and locate the following section:
<system.web.webPages.razor>
        <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
        <pages pageBaseType="System.Web.Mvc.WebViewPage">
            <namespaces>
                <add namespace="System.Web.Mvc" />
                <add namespace="System.Web.Mvc.Ajax" />
                <add namespace="System.Web.Mvc.Html" />
                <add namespace="System.Web.Optimization"/>
                <add namespace="System.Web.Routing" />
                <add namespace="SharpSolutions..MvcApplication.Helpers.BootStrap"/>
                <add namespace="SharpSolutions.MvcApplication.Helpers"/>
            </namespaces>
        </pages>
    </system.web.webPages.razor>

and add your custom namespace to it.

After you have done this reload your mvc project (or close Visual Studio and reopen it).

Tuesday, March 01, 2011

EF CTP5 And Unit Testing

Using Entity Framework Code First CTP5 its quite easy to write and unit test your repositories. However test should still be written against the mappings of the actual database. It would be best to split the tests that write to the database from the tests that read into a different class

Just Create a class that inherits from DropCreateDatabaseAlways<T> override the seed method to create insert the values you want.
   1: public class DBContextInitializer : DropCreateDatabaseAlways<EntityContext>
   2: {
   3:     protected override void Seed(EntityContext context)
   4:     {
   5:         ProductDummies.GetAllProducts().ForEach(p => context.Set<Product>().Add(p));
   6:         context.Commit();
   7:     }
   8: }
And then put in your Unit Test Assembly the following method:

   1: [ClassInitialize]
   2: public static void ClassInitialize(TestContext context) {
   3:     DbDatabase.SetInitializer(new DBContextInitializer());
   4: }

If you then use an in memory database it will be fast. The best way to always start from a known state (and to avoid mstest concurrency problems is to put the following code in Your TestInitialize method:
   1: [TestInitialize]
   2: public void TestInitialize()
   3: {
   4:     string key = Guid.NewGuid().ToString();
   5:     TestContext.Properties.Add(DB_NAME_KEY, key);
   6:     repository = new Repository<Product>(key);
   7: }

To delete put the following snippet in your TestCleanUp
   1: [TestCleanup]
   2: public void TestCleanUp()
   3: {
   4:     repository.Dispose();
   5:     DbDatabase.Delete(TestContext.Properties[DB_NAME_KEY].ToString);
   6: }

Thursday, February 03, 2011

C# 4.0 Code Contracts:

I was trying out the code contracts in C# 4.0 and came across something quite surprising every time I ran my unit tests I got an annoying message box popping up “Assert Failure”, Description must use the rewriter when using Contract.Requires<TException>.

After some googling around I found that in Project Properties you need to find the code contracts tab and set “Perform Runtime Contract Checking” to full.

I opened my project properties I realized I did not have the Code Contracts tab… So in order to enable this tab you will need to install Code Contracts from DevLabs (here: http://msdn.microsoft.com/en-us/devlabs/dd491992.aspx).

Rebuild and he complained about the Assembly Mode Setting not being appropiate. After Changing it I could run my tests without having to click every time a testmethod came in the method that had the contract.

Problem solved!

Interface Contracts

One problem I came across is that when trying Interface contracts I had an assembly that ended in Contracts and apparently it does not work (Code Contracts will compile its contracts in a assembly named <assembly name>.Contracts.dll. I renamed the assembly to IContracts and everything worked as expected

Tuesday, August 10, 2010

TDD Example Write function that calcutates a Fibonacci number

Step 1:

   1:  [TestMethod]
   2:  public void FibonacciSequanceTest(){
   3:     Func<int, int> fib = null;
   4:   
   5:     Assert.AreEqual(0, fib(0));
   6:  }
Step 2:

   1:  [TestMethod]
   2:  public void FibonacciSequanceTest(){
   3:     Func<int, int> fib = (n) => { return n; };
   4:   
   5:     Assert.AreEqual(0, fib(0));
   6:  }
Wee first test case passed!
Step 3: Adding another testcase

   1:  [TestMethod]
   2:  public void FibonacciSequanceTest(){
   3:      Func<int, int> fib = (n) => { return n; };
   4:   
   5:   
   6:      Assert.AreEqual(0, fib(0));
   7:      Assert.AreEqual(1, fib(1));
   8:  }
Works again
Step 4: Removing duplication in the asserts
   1:  [TestMethod]
   2:  public void FibonacciSequanceTest(){
   3:      Func<int, int> fib = (n) => { return n; };
   4:   
   5:      Assert.AreEqual(0, fib(0));
   6:      Assert.AreEqual(1, fib(1));
   7:  }
Refactored gives:

   1:  [TestMethod]
   2:  public void FibonacciSequanceTest(){
   3:      Func<int, int> fib = (n) => {
   4:          return n;
   5:      };
   6:   
   7:      Dictionary<int, int> fibonacciSequence = new Dictionary<int, int>{
   8:                  {0 , 0},
   9:                  {1 , 1},
  10:              };
  11:   
  12:      foreach (KeyValuePair<int, int> row in fibonacciSequence)
  13:      {
  14:          Assert.AreEqual(row.Value, fib(row.Key));
  15:      }
  16:  }
Step 5: Adding another testcase

   1:  [TestMethod]
   2:  public void FibonacciSequanceTest(){
   3:      Func<int, int> fib = (n) => {
   4:          return n;
   5:      };
   6:   
   7:      Dictionary<int, int> fibonacciSequence = new Dictionary<int, int>{
   8:                  {0 , 0},
   9:                  {1 , 1},
  10:                  {2 , 1},
  11:              };
  12:   
  13:      foreach (KeyValuePair<int, int> row in fibonacciSequence)
  14:      {
  15:          Assert.AreEqual(row.Value, fib(row.Key));
  16:      }
  17:  }
Woops test failed!
Ok lets fix it:

   1:  [TestMethod]
   2:  public void FibonacciSequanceTest(){
   3:      Func<int, int> fib = (n) => {
   4:          if (n < 2) return n;
   5:          return 1;
   6:      };
   7:   
   8:      Dictionary<int, int> fibonacciSequence = new Dictionary<int, int>{
   9:                  {0 , 0},
  10:                  {1 , 1},
  11:                  {2 , 1},
  12:              };
  13:   
  14:      foreach (KeyValuePair<int, int> row in fibonacciSequence)
  15:      {
  16:          Assert.AreEqual(row.Value, fib(row.Key));
  17:      }
  18:  }
Test Fixed!
Step 6: Adding another test case and taking 2 steps at the time since 1 will never equal 2 but 1 = 2-1 and 2 = 3-1 and thus return n-1 will do the trick for now

   1:  [TestMethod]
   2:  public void FibonacciSequanceTest(){
   3:      Func<int, int> fib = (n) => {
   4:          if (n < 2) return n;
   5:          return n - 1;
   6:      };
   7:   
   8:      Dictionary<int, int> fibonacciSequence = new Dictionary<int, int>{
   9:                  {0 , 0},
  10:                  {1 , 1},
  11:                  {2 , 1},
  12:                  {3 , 2}
  13:              };
  14:   
  15:      foreach (KeyValuePair<int, int> row in fibonacciSequence)
  16:      {
  17:          Assert.AreEqual(row.Value, fib(row.Key));
  18:      }
  19:  }
 
 
Step 7: adding 2 more test cases (since the next we add will work fine too :))


   1:  [TestMethod]
   2:  public void FibonacciSequanceTest(){
   3:      Func<int, int> fib = (n) => {
   4:          if (n < 2) return n;
   5:          return n - 1;
   6:      };
   7:   
   8:      Dictionary<int, int> fibonacciSequence = new Dictionary<int, int>{
   9:                  {0 , 0},
  10:                  {1 , 1},
  11:                  {2 , 1},
  12:                  {3 , 2},
  13:                  {4 , 3},
  14:                  {5 , 5}
  15:              };
  16:   
  17:      foreach (KeyValuePair<int, int> row in fibonacciSequence)
  18:      {
  19:          Assert.AreEqual(row.Value, fib(row.Key));
  20:      }
  21:  }
Test Fails again (the test case marked in red)
The solution (fast forwarded):
Because 5 = 2 + 3
From the testcases we can see that fib(3) = 2 and fib(4)=3
And thus 5 = fib(3) + fib(4)
3 = 5 - 2 and 4 = 5 - 1
5 = n and this 5 = fib(n-2) + fib(n-1)

   1:  [TestMethod]
   2:  public void FibonacciSequanceTest(){
   3:      Func<int, int> fib = (n) => {
   4:          if (n < 2) return n;
   5:          return fib(n - 1) + fib(n - 2);
   6:      };
   7:   
   8:      Dictionary<int, int> fibonacciSequence = new Dictionary<int, int>{
   9:                  {0 , 0},
  10:                  {1 , 1},
  11:                  {2 , 1},
  12:                  {3 , 2},
  13:                  {4 , 3},
  14:                  {5 , 5}
  15:              };
  16:   
  17:      foreach (KeyValuePair<int, int> row in fibonacciSequence)
  18:      {
  19:          Assert.AreEqual(row.Value, fib(row.Key));
  20:      }
  21:  }
Does not compile :( Error: use of unsigned variable
The fix:
   1:  [TestMethod]
   2:  public void FibonacciSequanceTest(){
   3:      Func<int, int> fib = null;
   4:          fib = (n) => {
   5:          if (n < 2) return n;
   6:          return fib(n - 2) + fib(n - 1);
   7:      };
   8:   
   9:      Dictionary<int, int> fibonacciSequence = new Dictionary<int, int>{
  10:                  {0 , 0},
  11:                  {1 , 1},
  12:                  {2 , 1},
  13:                  {3 , 2},
  14:                  {4 , 3},
  15:                  {5 , 5}
  16:              };
  17:   
  18:      foreach (KeyValuePair<int, int> row in fibonacciSequence)
  19:      {
  20:          Assert.AreEqual(row.Value, fib(row.Key));
  21:      }
  22:  }

Et voila done!

Friday, February 26, 2010

MVP in asp .net / sharepoint

The view interface



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

namespace SharpSoutions.MVP
{
public interface IView
{
Model DataSource { get; set; }
void DataBind();
void UpdateModel();

event EventHandler Saved;
}
}




using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SharpSoutions.MVP.Domain;

namespace SharpSoutions.MVP
{
[Serializable]
public class Model
{
public Person NewPerson { get; set; }

public Title[] Titles { get; set; }
}
}


The presenter



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SharpSoutions.MVP.Domain;
using System.Diagnostics;

namespace SharpSoutions.MVP
{
public class Presenter
{
private Data.IRepository<Title> titleRepository;
private Data.IRepository<Person> personRepository;


public Presenter(Data.IRepository<Title> titleRepository, Data.IRepository<Person> personRepository)
{
Trace.TraceInformation("Begin Presenter.Ctor");
this.titleRepository = titleRepository;
this.personRepository = personRepository;

this.Model = new Model();
this.Model.NewPerson = new Person();
Trace.TraceInformation("End Presenter.Ctor");
}

public Model Model { get; set; }

public IView View { get; set; }

/// <summary>
/// Init populates the "static" data
/// These are the data that is shown in dropdown boxes etc
/// </summary>
/// <param name="mockView"></param>
public void Init(IView view)
{
Trace.TraceInformation("Begin Presenter.Init");
AttachView(view);
this.View.DataSource = this.Model;

this.Model.Titles = this.titleRepository.Query();

this.View.DataBind();
Trace.TraceInformation("End Presenter.Init");
}

public void AttachView(IView view) {
this.View = view;
this.View.Saved += new EventHandler(View_Saved);

}

void View_Saved(object sender, EventArgs e)
{
System.Diagnostics.Trace.TraceInformation("Begin Presenter.View_Saved");
this.Save();
System.Diagnostics.Trace.TraceInformation("End Presenter.View_Saved");
}

public void Save()
{
System.Diagnostics.Trace.TraceInformation("Begin Presenter.Save");
this.View.UpdateModel();

personRepository.Update(this.Model.NewPerson);
System.Diagnostics.Trace.TraceInformation("End Presenter.Save");
}
}
}


The View implementation



using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using SharpSoutions.MVP.Domain;

namespace SharpSoutions.MVP.Web
{
public partial class View : System.Web.UI.UserControl, IView
{


public Model DataSource{
get {
if (ViewState["d"] != null) {
return (Model)ViewState["d"];
}

return null;
}

set {
ViewState["d"] = value;
}
}

public override void DataBind()
{
System.Diagnostics.Trace.TraceInformation("Begin View.Databind");
base.DataBind();

TitleDropDown.DataSource = this.DataSource.Titles;
if (this.DataSource.NewPerson.Title != null) {
TitleDropDown.SelectedValue = this.DataSource.NewPerson.Title.Id.ToString();
}

TitleDropDown.DataTextField = "Name";
TitleDropDown.DataValueField = "Id";
TitleDropDown.DataBind();

nameTextbox.Text = this.DataSource.NewPerson.Name;
System.Diagnostics.Trace.TraceInformation("End View.Databind");
}


public void UpdateModel()
{
System.Diagnostics.Trace.TraceInformation("Begin View.UpdateModel");
this.DataSource.NewPerson.Name = nameTextbox.Text;
ListItem selectedTitle = TitleDropDown.SelectedItem;
this.DataSource.NewPerson.Title = new Title { Id = int.Parse(selectedTitle.Value), Name = selectedTitle.Text };
System.Diagnostics.Trace.TraceInformation("End View.UpdateModel");
}

public event EventHandler Committed;

protected void SaveButton_Click(object sender, EventArgs e)
{
System.Diagnostics.Trace.TraceInformation("Begin View.SaveButton_Click");

if (this.Saved != null) {
this.Saved(this, EventArgs.Empty);
}
System.Diagnostics.Trace.TraceInformation("End View.SaveButton_Click");
}


public event EventHandler Saved;
}
}

Monday, September 07, 2009

Implementing INotifyPropertyChanged by using Unity Interception

This example uses Unity interception to be able to bind objects to a UI by just applying a [Notify] attribute to a property, this done by intercepting the call and propagating it to a INotifyPropertyChanged implementation.
From MSDN:
The INotifyPropertyChanged interface is used to notify clients, typically binding clients, that a property value has changed.

Step 1 create an abstract class that encapsulates all the functionality we need.
See below for a class diagram:


Step 2 create the handler:
NotifyPropertyChangedHandler which inherits from ICallHandler
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext) {

IMethodReturn result = getNext()(input, getNext);

if (!input.MethodBase.Name.StartsWith("set_")) return result;
//Remov the set_ to get the property's name
var propertyName = input.MethodBase.Name.Remove(0, 4);
//invoke the modified property
//maybe we should check if the target is indeed o BindableOjectBase ;)
BindableObjectBase target = (BindableObjectBase)input.Target;
((IBindableObject)target).Modified(propertyName);
return result;
}

Step 3: Create the attribute
Create a NotifyPropertyChangedAttribute class which inherits from HandlerAttribute
create a default constructor:
public NotifyPropertyChangedAttribute() {
_CallHandler = new NotifyPropertyChangedHandler();
}

override the folowing method
public override ICallHandler CreateHandler(IUnityContainer container) {
return _CallHandler;
}
Step 4: Setting up the UnityContainer:
UnityContainer_Container = new UnityContainer();
//Registring interception extension
_Container.AddNewExtension();
_Container.RegisterInstance(instance);
_Container.Configure().SetDefaultInterceptorFor(new TransparentProxyInterceptor());
var object container.Resolve();

the last step took a little time to get it working the way I wanted since DI usually works by injecting interface implementations but this was not what I wanted to do. Since interfaces define behaviour and properties have nothing to do with behaviour but with state.

I will post the full source code later

Wednesday, December 31, 2008

XP And new years resolutions

At the verge on a new year people tend to have new years resolutions and things like that mine is blog more :p amongst others. So here we go.

I recently started reading Ron Jeffries Extreme Programming Adventures in C# (http://www.amazon.com/Extreme-Programming-Adventures-DV-Microsoft-Professional/dp/0735619492). Since quite a little more then a year I Agile Development Methodologies caught my eye. Recently I am starting to dig deeper in TDD and XP. In this series of posts I will let you follow me on my journey.

Monday, September 24, 2007

Create A Compression extension using .NET 2.0
(original version can be found here: http://www.123aspx.com/redir.aspx?res=29459)

First of all we create a class that does all the work



public class CompressionExtension : SoapExtension {
Stream _OldStream;
Stream _NewStream;


public override object GetInitializer(LogicalMethodInfo methodInfo,
SoapExtensionAttribute attribute) {
return attribute;
}

// Get the Type
public override object GetInitializer(Type t) {
return typeof(CompressionExtension);
}

// Get the CompressionExtensionAttribute
public override void Initialize(object initializer) {
if (initializer is CompressionExtensionAttribute) {
CompressionExtensionAttribute attribute =
(CompressionExtensionAttribute)initializer;
}


return;
}

// Process the SOAP Message
public override void ProcessMessage(SoapMessage message) {
// Check for the various SOAP Message Stages
switch (message.Stage) {

case SoapMessageStage.BeforeSerialize:
break;

case SoapMessageStage.AfterSerialize:
// ZIP the contents of the SOAP Body after it has
// been serialized
Zip();
break;

case SoapMessageStage.BeforeDeserialize:
// Unzip the contents of the SOAP Body before it is
// deserialized
Unzip();
break;

case SoapMessageStage.AfterDeserialize:
break;

default:
throw new Exception("invalid stage");
}
}

// Gives us the ability to get hold of the RAW SOAP message
public override Stream ChainStream(Stream stream) {
_OldStream = stream;
_NewStream = new MemoryStream();
return _NewStream;
}

// Utility method to copy streams
void Copy(Stream from, Stream to) {
TextReader reader = new StreamReader(from);
TextWriter writer = new StreamWriter(to);
writer.WriteLine(reader.ReadToEnd());
writer.Flush();
}


// Zip the SOAP Body
private void Zip() {
_NewStream.Position = 0;
// Zip the SOAP Body
_NewStream = ZipSoap(_NewStream);
// Copy the streams
Copy(_NewStream, _OldStream);
}

// The actual ZIP method
private byte[] Zip(string stringToZip) {
byte[] inputByteArray = Encoding.UTF8.GetBytes(stringToZip);
MemoryStream ms = new MemoryStream();

// Check the #ziplib docs for more information
GZipStream zipOut = new GZipStream(ms, CompressionMode.Compress);
zipOut.Write(inputByteArray, 0, inputByteArray.Length);
zipOut.Close();

// Return the zipped contents
return ms.ToArray();
}

// Select and Zip the appropriate parts of the SOAP message
public MemoryStream ZipSoap(Stream streamToZip) {
streamToZip.Position = 0;
// Load a XML Reader
XmlTextReader reader = new XmlTextReader(streamToZip);
XmlDocument dom = new XmlDocument();
dom.Load(reader);
// Load a NamespaceManager to enable XPath selection
XmlNamespaceManager nsmgr = new XmlNamespaceManager(dom.NameTable);
nsmgr.AddNamespace("soap", "http://schemas.xmlsoap.org/soap/envelope/");
XmlNode node = dom.SelectSingleNode("//soap:Body", nsmgr);
// Select the contents within the method defined in the SOAP body
node = node.FirstChild.FirstChild;
// Check if there are any nodes selected
while (node != null) {
if (node.InnerXml.Length > 0) {
// Zip the data
byte[] outData = Zip(node.InnerXml);
// Convert it to Base64 for transfer over the internet
node.InnerXml = Convert.ToBase64String(outData);
}
// Move to the next parameter
node = node.NextSibling;
}
MemoryStream ms = new MemoryStream();
// Save the updated data
dom.Save(ms);
ms.Position = 0;

return ms;
}

// Unzip the SOAP Body
private void Unzip() {
MemoryStream unzipedStream = new MemoryStream();

TextReader reader = new StreamReader(_OldStream);
TextWriter writer = new StreamWriter(unzipedStream);
writer.WriteLine(reader.ReadToEnd());
writer.Flush();
// Unzip the SOAP Body
unzipedStream = UnzipSoap(unzipedStream);
// Copy the streams
Copy(unzipedStream, _NewStream);

_NewStream.Position = 0;
}

// Actual Unzip logic
private byte[] Unzip(string stringToUnzip) {
// Decode the Base64 encoding
byte[] inputByteArray = Convert.FromBase64String(stringToUnzip);
MemoryStream ms = new MemoryStream(inputByteArray);
MemoryStream ret = new MemoryStream();

// Refer to #ziplib documentation for more info on this
GZipStream zipIn = new GZipStream(ms, CompressionMode.Decompress);
Byte[] buffer = new Byte[2048];
int size = 2048;
while (true) {
size = zipIn.Read(buffer, 0, buffer.Length);
if (size > 0) {
ret.Write(buffer, 0, size);
} else {
break;
}
}
return ret.ToArray();
}

// Unzip the SOAP Body
public MemoryStream UnzipSoap(Stream streamToUnzip) {
streamToUnzip.Position = 0;
// Load a XmlReader
XmlTextReader reader = new XmlTextReader(streamToUnzip);
XmlDocument dom = new XmlDocument();
dom.Load(reader);

XmlNamespaceManager nsmgr = new XmlNamespaceManager(dom.NameTable);
nsmgr.AddNamespace("soap", "http://schemas.xmlsoap.org/soap/envelope/");
// Select the SOAP Body node
XmlNode node = dom.SelectSingleNode("//soap:Body", nsmgr);
node = node.FirstChild.FirstChild;

// Check if node exists
while (node != null) {
if (node.InnerXml.Length > 0) {
// Send the node's contents to be unziped
byte[] outData = Unzip(node.InnerXml);
string sTmp = Encoding.UTF8.GetString(outData);
node.InnerXml = sTmp;
}
// Move to the next parameter
node = node.NextSibling;
}

MemoryStream ms = new MemoryStream();

dom.Save(ms);
ms.Position = 0;

return ms;
}

}


Next we create a class that will be able to use as an attribute



public class CompressionExtensionAttribute : System.Web.Services.Protocols.SoapExtensionAttribute {

private int _Priority;

// Override the base class properties
public override Type ExtensionType {
get { return typeof(CompressionExtension); }
}

public override int Priority {
get {
return _Priority;
}
set {
_Priority = value;
}
}
}



This approach involves updating the reference.cs manually. We are going to extend this in order that if we choose update webreference in Visual studion the attribute is added immediately to the proxy class. (For more detail goto: http://msdn2.microsoft.com/en-us/library/x4s9z3yc.aspx)

Friday, April 20, 2007

Create a Winforms ComboBox with a default text when nothing is selected.

Follow these easy steps to create a combox that shows a text instead of an empty line when nothing is selected


  • Create a new UserControl

  • in the code view make sure the Class Enherits from ComboBox instead of UserControl

  • In the default constructor set the DrawMode to OwnerDrawn.

  • Add two properties UnSelectedColor of type Color and UnSelectedText of type string

  • Override the OnDrawItem method


I will put a more detailed article on my personal homepage. Link will follow later.

Thanks to Richard Everett who provided me the example code

Monday, April 16, 2007

Easy way for filtering a BindingList


Found this opensource project: http://sourceforge.net/projects/blw/

As a replacement for datasets/dataTables

Tuesday, March 06, 2007

I came across an annoying little thing trying to trigger an event that updates the UI...

{"Cross-thread operation not valid: Control 'label1' accessed from a thread other than the thread it was created on."}


This happens because the UI runs in a specific thread. Now we create another thread and try to access the UI thread which throws the above exception. There is a solution in msdn but imo its not a good one.

Thus we need to marshal the event from one thread to the other thread as shown below.

the source (just create a new form called form1 and drag a label and a button on it):

ThreadComponent.cs


using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.ComponentModel;


namespace WindowsApplication3 {
public delegate void ShowSomethingHandler(string message);


public class ThreadedComponent {
private Thread _Thread;

public ThreadedComponent() {
_Thread = new Thread(Poll);
_Thread.Start();

}

private void Poll() {
int i = 0;
ISynchronizeInvoke invoker = ShowSomething.Target as ISynchronizeInvoke;
while(true) {
if(ShowSomething != null) {

//ShowSomething("Message N°:" + (++i));
if(!invoker.InvokeRequired) {
object[] args = {"Message N°:" + (++i)};
invoker.Invoke(ShowSomething, args);
} else {
ShowSomething("Message N°:" + (++i));
}


}
Thread.Sleep(1000);
}
}

public event ShowSomethingHandler ShowSomething;
}
}



Form1.cs

namespace WindowsApplication3 {
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}

private void button1_Click(object sender, EventArgs e) {
ThreadedComponent c = new ThreadedComponent();
c.ShowSomething += new ShowSomethingHandler(c_ShowSomething);
}

void c_ShowSomething(string message) {
label1.Text = message;
}
}
}