Create Windows Service that will just write to log In Visual Studio 2010, create new project, Windows group, Windows service
in Service1.cs, OnStart(string[] args) {...} add an action that the service will start. The method has to return in 30 seconds.
Debug.Listeners.Add(new TextWriterTraceListener(System.IO.File.Create(@"c:\_delete\trace.txt")));
Trace.AutoFlush = true;
Trace.WriteLine("starting");
More info and samples on: www.devarchweb.net
How to specify credentials for Windows service 1. Programatically:// ProjectInstaller.Designer.cs
private void InitializeComponents() {
...
this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalSystem;
this.serviceProcessInstaller1.Password = null;
this.serviceProcessInstaller1.Username = null;
...
}
More info and samples on: www.devarchweb.net
Write a code that populates common members of PersonLite and Person (inherits from PersonLite) classes using genericsprivate class PersonLite
{
internal int Id;
internal string Name;
}
private class Person : PersonLite
{
internal DateTime BirthDay;
}
internal static void ShowBasics()
{
PersonLite personLite = new PersonLite();
Populate(personLite);
Person person = new Person();
Populate(person);
person.BirthDay = DateTime.Parse("1969-01-01");
}
private static void Populate<T>(T p) where T : PersonLite
{
// read data from external source, e.g. DB
p.Id = 1;
p.Name = "John";
}
More info and samples on: www.devarchweb.net
Create a generic method that returns new object of type Tprivate class PersonLite
{
internal int Id;
internal string Name;
}
private class Person : PersonLite
{
internal DateTime BirthDay;
}
internal static void DemoCreateNewObject()
{
PersonLite personLite = CreateNew<PersonLite>();
Person person = CreateNew<Person>();
}
private static T CreateNew<T>() where T : PersonLite, new()
{
T result = new T();
result.Name = "new";
return result;
}
More info and samples on: www.devarchweb.net
Create list based on generic type (Person or PersonLite) passed inprivate class PersonLite
{
internal int Id;
internal string Name;
}
private class Person : PersonLite
{
internal DateTime BirthDay;
}
internal static void DemoLoadDataBasedOnType()
{
List<PersonLite> list = CreateList<PersonLite>();
List<Person> list2 = CreateList<Person>();
}
private static List<T> CreateList<T>() where T : PersonLite, new() // new() is needed New<T>()
{
List<T> result = new List<T>();
Type t = typeof(T);
int count = 1;
switch (t.Name)
{
// this can be used to generate a SQL query
case "PersonLite": count = 2; break;
case "Person": count = 3; break;
}
for (int i = 0; i < count; i++)
{
T item = new T();
item.Name = "new";
result.Add(item);
}
return result;
}
More info and samples on: www.devarchweb.net
Explain dynamic If an object is defined as dynammic, it bypasses static type checks at compile timeDateTime date = new DateTime();
// date.AddCentury(1); fails at compile time
dynamic dateDynamic = new DateTime();
dateDynamic.AddCentury(1); // fails at runtime
var obj = date as dynamic;
obj.AddCentury(); // fails at runtime
More info and samples on: www.devarchweb.net
Convert Enum to string and backpublic enum Department
{
IT,
Finance
}
string text = Enum.GetName(IT.GetType(), IT);
Department d = (Department) Enum.Parse(typeof(Department), "IT");
More info and samples on: www.devarchweb.net
What are immutable classes, what is the problem, how could it be prevented? http://tipsandtricks.runicsoft.com/CSharp/Immutables.htmlMore info and samples on: www.devarchweb.net
How to identify assembly architecture corflags myassembly.exeMore info and samples on: www.devarchweb.net
What is mixed mode assembly Source MSDN: Mixed assemblies are capable of containing both unmanaged machine instructions and MSIL instructions. This allows them to call and be called by .NET components, while retaining compatibility with components that are entirely unmanaged. Using mixed assemblies, developers can author applications using a mixture of managed and unmanaged functionality. This makes mixed assemblies ideal for migrating existing Visual C++ applications to the .NET Platform.More info and samples on: www.devarchweb.net
How list and array get placed in LOH List is implented using an array and when new item is added, a new and larger array is allocatedMore info and samples on: www.devarchweb.net
Type of GC roots Local variables: are kept alive as long as the method is on call stack (in Release build, JIT can unmark it before the method exits)More info and samples on: www.devarchweb.net
Type of memory leaks and how to solve them Holding references to managed objects (e.g. event handlers):More info and samples on: www.devarchweb.net
Available memory resources per 32 and 64 bit systems On 32 bit system a program can use up to 1.5G memoryMore info and samples on: www.devarchweb.net
GC modes Concurent (desktop apps): GC will not stop the app, the app will just slow.More info and samples on: www.devarchweb.net
Impact of using GC.Collect() Using GC.Collect() will cause newly created objects released later (moved to Gen 2) which increases the likelihood of another expensive full collection in the near future.More info and samples on: www.devarchweb.net
Example of extension method that adds a method with new name and extends method with the same namesealed class SealedClass
{
internal void DoSomething()
{
Console.WriteLine("SealedClass.DoSomething()");
}
// cannot be called from extension method
protected void DoSomethingProtected()
{
Console.WriteLine("SealedClass.DoSomethingProtected()");
}
internal static void DoSomethingStatic()
{
Console.WriteLine("SealedClass.DoSomethingStatic()");
}
}
static class ExtensionClass
{
internal static void DoSomething(this SealedClass sealedClass)
{
Console.WriteLine("Gets never called");
}
internal static void DoSomething(this SealedClass sealedClass, int i)
{
sealedClass.DoSomething(); // class method can be called
// sealedClass.DoSomethingProtected(); not available
Console.WriteLine("ExtensionClass.DoSomething(int i)");
}
internal static void DoSomethingElse(this SealedClass sealedClass)
{
Console.WriteLine("ExtensionClass.DoSomethingElse()");
}
internal static void DoSomethingStatic(this SealedClass sealedClass)
{
Console.WriteLine("Gets never called");
}
}
class ExtensionMethodsDemo
{
internal static void DemoExtensionMethods()
{
SealedClass sealedClass = new SealedClass();
sealedClass.DoSomething(); // calls SealedClass
sealedClass.DoSomething(1); // calls ExtensionClass
sealedClass.DoSomethingElse(); // calls ExtensionClass
SealedClass.DoSomethingStatic(); // calls SealedClass
}
}
More info and samples on: www.devarchweb.net
Write tracing information to log file, console and event log// trace to a text file
TextWriterTraceListener textWriterTraceListener = new TextWriterTraceListener(LOG_FILE_NAME);
textWriterTraceListener.TraceOutputOptions = TraceOptions.DateTime | TraceOptions.ProcessId | TraceOptions.ThreadId;
Trace.Listeners.Add(textWriterTraceListener);
// trace to the console
Trace.Listeners.Add(new ConsoleTraceListener());
// trace to event log
// !! this code must be executed als administrator when the source Basics.exe does not exist
ventLogTraceListener eventLogTraceListener = new EventLogTraceListener("Basics.exe");
Trace.WriteLine("Written by Trace.WriteLine()");
Trace.Flush();
Trace.AutoFlush = true;
Trace.TraceInformation("Written by Trace.TraceInformation"); // writes datetime + process id + thread id
Trace.TraceWarning("Written by Trace.TraceWarning");
Trace.TraceError("Written by Trace.TraceError");
More info and samples on: www.devarchweb.net
Create TextWriterTraceListener in app.config <configuration>
<system.diagnostics>
<trace autoflush="true">
<listeners>
<remove name="Default"/>
<add name="textWriterTraceListenerConfig"
type="System.Diagnostics.TextWriterTraceListener"
traceOutputOptions="DateTime,Timestamp,Callstack,LogicalOperationStack,ProcessId,ThreadId"
initializeData="MyLogFromConfig.log">
</add>
</listeners>
</trace>
</system.diagnostics>
</configuration>
More info and samples on: www.devarchweb.net
Create a trace listener with filterTextWriterTraceListener textWriterTraceListener = new TextWriterTraceListener(LOG_FILE_NAME);
EventTypeFilter e = new EventTypeFilter(SourceLevels.Error); // .Error: Verbose, Information, Warning are ignored
textWriterTraceListener.Filter = e;
Trace.Listeners.Add(textWriterTraceListener);
Trace.TraceWarning("DemoEventTraceWithFilter - Trace warning"); // will be ignored (by filter)
Trace.TraceError("DemoEventTraceWithFilter - Trace error"); // will be written
<add name="textWriterTraceListenerConfig"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="MyLogFromConfig.log">
<filter type="System.Diagnostics.EventTypeFilter" initializeData="Warning"/>
</add>
More info and samples on: www.devarchweb.net
TraceSwitch to filter messagesTraceSwitch traceSwitch = new TraceSwitch("textWriterTraceListener", "description" );
traceSwitch.Level = TraceLevel.Warning;
// Off 0, Error 1, Warning 2 default, Info 3, Verbose 4
TextWriterTraceListener textWriterTraceListener = new TextWriterTraceListener(LOG_FILE_NAME);
Trace.Listeners.Add(textWriterTraceListener);
Trace.WriteLine("switch controlled - no IF");
Trace.WriteLineIf(traceSwitch.TraceVerbose, "switch controlled verbose"); // will be ignored
Trace.WriteLineIf(traceSwitch.TraceError, "switch controlled error");
Trace.Flush();
<system.diagnostics>
<switches>
<add name="textWriterTraceListener" value="3"/>
</switches>
...
More info and samples on: www.devarchweb.net
Write to Event Logstring myAppName = "Basics3.exe"; // event source name must be unique accross all logs
// Write to application log
EventLog eventLog = new EventLog("Application", Environment.MachineName, myAppName);
EventLog.WriteEntry(myAppName, "Demo error", EventLogEntryType.Error); // !! this code must be executed als administrator when the source does not exist
// Write to custom log
EventLog customEventLog = new EventLog("ZbynekDemo1", Environment.MachineName, myAppName + "Custom");
customEventLog.WriteEntry("Demo error", EventLogEntryType.Error); // first time you have to close and open Event Viewer to see the new custom event log
More info and samples on: www.devarchweb.net
How to enable and create and configure console logger in Log4net Install log4net NuGet package (log4net.dll will be added to project references)using log4net;
using log4net.Config;
namespace Log4NetBasics
{
class Program
{
private static readonly ILog _logger = LogManager.GetLogger("MyLogger");
static void Main(string[] args)
{
XmlConfigurator.Configure(); // read the configuration from app.config
// BasicConfigurator.Configure(); // ! does not read configuration for File or Debug appenders
_logger.Info("Info message");
_logger.Warn("Warning message");
_logger.Error("Error message");
Console.ReadLine();
}
}
}
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" />
</configSections>
<log4net>
<appender name="Console" type="log4net.Appender.ColoredConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
</layout>
</appender>
<root>
<level value="ALL"/>
<appender-ref ref="Console"/>
</root>
</log4net>
</configuration>
More info and samples on: www.devarchweb.net
How to format message for log4net and include own property<log4net>
<appender name="Console" type="log4net.Appender.ColoredConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger %property{myData} (%file:%line): %message %newline"/>
</layout>
</appender>
...
</log4net>
GlobalContext.Properties["myData"] = "abc";
More info and samples on: www.devarchweb.net
How to define color for messages for og4net<log4net>
<appender name="Console" type="log4net.Appender.ColoredConsoleAppender">
<mapping>
<level value="ERROR"/>
<foreColor value="Red"/>
</mapping>
...
</appender>
...
</log4net>
More info and samples on: www.devarchweb.net
Using file and debug appenders in Log4net Adding another listeners, called appenders, can be done the same way in app.config<log4net>
<appender name="File" type="log4net.Appender.RollingFileAppender">
<param name="File" value="c:\\temp\\log4netBasics.log"/>
<param name="AppendToFile" value="true"/>
<maximumFileSize value="100KB" />
<maxSizeRollBackups value="2" />
<layout type="log4net.Layout.PatternLayout"></layout>
</appender>
<appender name="DebuggerAppender" type="log4net.Appender.DebugAppender">
<layout type="log4net.Layout.PatternLayout">
</layout>
</appender>
...
</log4net>
More info and samples on: www.devarchweb.net
How to output current class and method (for logging)private static void Log(string message)
{
var frame = new StackFrame(skipFrames: 1); // 1 will get the frame of the caller of the Log method
System.Reflection.MethodBase callingMethod = frame.GetMethod();
Console.WriteLine("Class: {0} Method: {1}", callingMethod.DeclaringType.Name, callingMethod);
}
More info and samples on: www.devarchweb.net
Configure value in default app config and read it in code app.config file contains key-vaulue pair<configuration>
<appSettings>
<add key="key1" value="value1" />
</appSettings>
</configuration>
string settingValue = System.Configuration.ConfigurationManager.AppSettings["key1"];
More info and samples on: www.devarchweb.net
Get and set values in default config file Configuration values in default app.config cannot be modified, because the is no setter definedtry
{
System.Configuration.ConfigurationManager.AppSettings.Add("added", "added value");
}
catch (ConfigurationErrorsException ex)
{
Console.WriteLine(ex);
// "The configuration is write protected" exception. When executed from VS or Basics.exe.
}
More info and samples on: www.devarchweb.net
Get value from specific configExeConfigurationFileMap map = new System.Configuration.ExeConfigurationFileMap();
map.ExeConfigFilename = "app1.config"; // this can be used for Basics.exe.config or Basics.vshost.exe.config as well
Configuration mappedConfiguration = ConfigurationManager.OpenMappedExeConfiguration(map, System.Configuration.ConfigurationUserLevel.None);
AppSettingsSection appSettingsSection = (AppSettingsSection)mappedConfiguration.GetSection("appSettings");
// Get
string settings = appSettingsSection.Settings["key2"].Value;
// Add
appSettingsSection.Settings.Add("addedKey", "addedValue");
mappedConfiguration.Save();
// Remove
appSettingsSection.Settings.Remove("addedKey");
mappedConfiguration.Save();
More info and samples on: www.devarchweb.net
How to use properties for configuration Another way how to store configuration data is to use Properties.Settings class.<configuration>
<configSections>
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="Basics.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
<sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="Basics.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</sectionGroup>
</configSections>
<userSettings>
<Basics.Properties.Settings>
<setting name="MySettingForUser" serializeAs="String">
<value>user</value>
</setting>
</Basics.Properties.Settings>
</userSettings>
<applicationSettings>
<Basics.Properties.Settings>
<setting name="MySettingForApp" serializeAs="String">
<value>app</value>
</setting>
</Basics.Properties.Settings>
</applicationSettings>
</configuration>
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
[global::System.Configuration.UserScopedSettingAttribute()]
public string MySettingForUser {
get {
return ((string)(this["MySettingForUser"]));
}
set {
this["MySettingForUser"] = value;
}
}
}
// get application scope setting value
string value = Properties.Settings.Default.MySettingForApp;
// Properties.Settings.Default.SettingApp = value + "x"; does not compile, SettingApp has no setter
// get and set user scope setting value
string userValue = Properties.Settings.Default.MySettingForUser;
Properties.Settings.Default.MySettingForUser = userValue + "+";
Properties.Settings.Default.Save();
More info and samples on: www.devarchweb.net
Create simple custom section in config Define class representing the sectionclass ConfigurationElementSimple : System.Configuration.ConfigurationSection
{
[System.Configuration.ConfigurationProperty("myValue", IsRequired = true)]
public string MyValue
{
get { return (string)base["myValue"]; }
set { base["myValue"] = value; }
}
[System.Configuration.ConfigurationProperty("myNumber", IsRequired = false)]
public int MyNumber
{
get { return (int)base["myNumber"]; }
set { base["myNumber"] = value; }
}
}
<configuration>
<configSections>
<section name="simpleCustomSection" type="Basics.ConfigurationElementSimple, Basics"/>
<section name="simpleCustomSection2" type="Basics.ConfigurationElementSimple, Basics"/>
</configSections>
<simpleCustomSection myValue="abc" myNumber="1" />
<configuration>
ConfigurationElementSimple config = (ConfigurationElementSimple)System.Configuration.ConfigurationManager.GetSection("simpleCustomSection");
config = (ConfigurationElementSimple)System.Configuration.ConfigurationManager.GetSection("simpleCustomSection2");
More info and samples on: www.devarchweb.net
Create complex custom section with list in config Define class representing the section including the collection with its items.public class ConfigurationCollectionItem : ConfigurationElement
{
[ConfigurationProperty("name", IsRequired = true, IsKey = true)]
public string Name
{
get { return (string)base["name"]; }
}
[ConfigurationProperty("detail", IsRequired = false, IsKey = true)]
public string Detail
{
get { return (string)base["detail"]; }
}
public string UniqueName
{
get { return string.Format("{0}{1}", Name, Detail); }
}
}
public class MyConfigurationCollection : ConfigurationElementCollection
{
public ConfigurationCollection() { }
protected override ConfigurationElement CreateNewElement()
{
return new ConfigurationCollectionItem();
}
protected override Object GetElementKey(ConfigurationElement element)
{
return ((ConfigurationCollectionItem)element).UniqueName;
}
}
public class ConfigurationElementComplex : ConfigurationSection
{
[ConfigurationProperty("id", IsDefaultCollection = false, IsRequired = true)]
public string Id
{
get { return (string)base["id"]; }
}
[ConfigurationProperty("myList", IsDefaultCollection = false, IsRequired = true)]
public MyConfigurationCollection MyList
{
get { return (MyConfigurationCollection)base["myList"]; }
}
}
<configuration>
<configSections>
<section name="complexCustomSection" type="Basics.ConfigurationElementComplex, Basics"/>
</configSections>
<complexCustomSection id="1">
<myList>
<add name="John" detail="abc" />
<add name="Paul" detail="def" />
</myList>
</complexCustomSection>
<configuration>
ConfigurationElementComplex config1 = (ConfigurationElementComplex)System.Configuration.ConfigurationManager.GetSection("complexCustomSection");
// string s = ((ConfigurationCollectionItem)config1.MyList[0]).Name; // access not allowed (config1.MyList[0])
foreach(var item in config1.MyList)
{
string name = ((ConfigurationCollectionItem)item).Name;
}
More info and samples on: www.devarchweb.net
Write a value, Read a value(2 ways) in registry, Test if values exists and delete it// create or overwrite registry value
Registry.SetValue(Registry.CurrentUser.Name + @"\Software\Zbynek Cernin\Basics", "TestValue", "abc");
// read registry value
string value = (string)Registry.GetValue(Registry.CurrentUser.Name + @"\Software\Zbynek Cernin\Basics", "TestValue", string.Empty);
// read registry value - using RegistryKey
RegistryKey basicsKey = Registry.CurrentUser.OpenSubKey(@"Software\Zbynek Cernin\Basics");
if (basicsKey != null)
{
value = (string)basicsKey.GetValue("TestValue");
value = (string)basicsKey.GetValue("TestValue1"); // does not exists - returns null
}
// test if values exists and delete it
basicsKey = Registry.CurrentUser.OpenSubKey(@"Software\Zbynek Cernin\Basics", writable: true);
if (basicsKey != null)
{
if (basicsKey.GetValueNames().Where(s => s == "TestValue").Count() > 0)
{
basicsKey.DeleteValue("TestValue");
}
}
More info and samples on: www.devarchweb.net
Create message queue// this code has to run as Admin
System.Messages.MessageQueue.Create(@".\Private$\MyQueue");
More info and samples on: www.devarchweb.net
Read messages synchronouslyif (MessageQueue.Exists(@".\Private$\MyQueue"))
{
MessageQueue mq = new MessageQueue(@".\Private$\MyQueue");
// send
mq.Send("Hello " + DateTime.Now.ToString(), "Title");
// receive
Message msg = mq.Receive();
};
More info and samples on: www.devarchweb.net
Read messages asynchronouslystatic void WriteAndReadMessageAsynchronously()
{
MessageQueue mq = new MessageQueue(@".\Private$\MyQueue");
mq.Send("Hello " + DateTime.Now.ToString(), "Title");
mq.ReceiveCompleted += new ReceiveCompletedEventHandler(MessageReceived);
mq.BeginReceive();
}
public static void MessageReceived(object source, ReceiveCompletedEventArgs args)
{
MessageQueue mq = (MessageQueue)source;
Message msg = mq.EndReceive(args.AsyncResult);
string body = (string)msg.Body;
}
More info and samples on: www.devarchweb.net
Create class instance from its nameinternal class Person
{
internal int ID;
internal string Name;
}
// arguments: assembly name, full class name with namespace
Person p = new Person() { ID = 1 };
object p1 = Activator.CreateInstance("Basics", "Basics.Person").Unwrap();
p = (Person)p1;
More info and samples on: www.devarchweb.net
Can you compare secure stringsSystem.Security.SecureString NewPassword;
System.Security.SecureString NewPassword2;
NewPassword.Clear();
NewPassword.AppendChar('a');
NewPassword2.Clear();
NewPassword2.AppendChar('a');
bool b = NewPassword2.Equals(NewPassword);
// b is FALSE
b = NewPassword.GetHashCode() == NewPassword.GetHashCode();
// b is FALSE
More info and samples on: www.devarchweb.net
Convert SecureString to stringIntPtr sPtr = IntPtr.Zero;
try
{
sPtr = Marshal.SecureStringToBSTR(securePassword);
String s1 = Marshal.PtrToStringBSTR(sPtr);
StringBuilder sb = new StringBuilder();
for (int i = 0; i < s1.Length; i++)
{
sb.Append(s1[i]);
}
return sb.ToString();
}
finally
{
if (ss_bstr1_ptr != IntPtr.Zero)
{
Marshal.ZeroFreeBSTR(ss_bstr1_ptr);
}
}
More info and samples on: www.devarchweb.net
Publish and subscribe string and int events with Caliburn// add reference to Caliburn.micro.dll
using Caliburn.Micro; // this is needed in order to see PublishOnUIThread extension method
public partial class MainForm : Form
{
internal static readonly Caliburn.Micro.IEventAggregator _eventAggregator = new Caliburn.Micro.EventAggregator();
public void Publish()
{
_eventAggregator.PublishOnUIThread("Hello from Caliburn");
_eventAggregator.PublishOnUIThread(123);
}
}
public partial class Form2Calibrun : Form, IHandle<string>, IHandle<int>
{
public Form2Calibrun()
{
...
MainForm._eventAggregator.Subscribe(this);
}
public new void Handle(string message)
{
label1.Text = (string)message;
}
public new void Handle(int message)
{
label1.Text = Convert.ToString(message);
}
}
More info and samples on: www.devarchweb.net
How to subscribe (with filter), handle, raise and unsubscribe events with EventAggregator (Prism)// define event object
public class MyStringEvent : PubSubEvent<string> { } // string event
public class Person
{
public int Id;
public string Name;
}
public class MyPersonEvent : PubSubEvent<Person> { } /
// create aggregator class
IEventAggregator _aggregator = new EventAggregator();
// subscribe events
_aggregator.GetEvent<MyStringEvent>().Subscribe(StringEventHandler);
_aggregator.GetEvent<MyPersonEvent>().Subscribe(PersonEventHandler);
// subscribe events with filter
SubscriptionToken unsubscribeToken = _aggregator.GetEvent<MyStringEvent>()
.Subscribe(StringEventHandler,
ThreadOption.UIThread,
keepSubscriberReferenceAlive: false,
filter: s => s.StartsWith("A"));
// handle events
private void StringEventHandler(string s) { ... }
private void PersonEventHandler(Person p) { ... }
// raise event
_aggregator.GetEvent<MyStringEvent>().Publish("Hello");
_aggregator.GetEvent<MyPersonEvent>().Publish(new Person() { Name = "John"} );
// unsubscribe
_aggregator.GetEvent<MyStringEvent>().Unsubscribe(StringEventHandler);
_aggregator.GetEvent<MyStringEvent>().Unsubscribe(unsubscribeToken);
More info and samples on: www.devarchweb.net
How use Lazy class to create a Singleton Lazy class can be used to create a thread safe singletonpublic sealed class MySingleton
{
private static readonly Lazy<MySingleton> lazy =
new Lazy<MySingleton>(() => new MySingleton());
public static MySingleton Instance { get { return lazy.Value; } }
private MySingleton()
{
}
}