Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

sontx/blackcat

Folders and files

NameName
Last commit message
Last commit date

Latest commit

History

45 Commits

Repository files navigation

blackcat

A bundle of dotnet utilities

Getting started

  1. Nuget:

Core library

Install-Package Blackcat -Version 1.0.1

Some utilities for WinForm flatform

Install-Package Blackcat.WinForm -Version 1.0.0
  1. Dll files (comming soon): release page
  2. Clone this repo as a submodule and add reference to your .net project

All important utilities

Configuration

Saves or loads configurations from file automatically.

Basic usage

  1. Defines your configuration class
public class MyConfig
{
 public string Config1 {get;set;}
 public int Config2 {get;set;}
}
  1. Gets configuration and use it
// MyConfig will be loaded from file or create new one if needed
var myConfig = ConfigLoader.Default.Get<MyConfig>();
textBox1.Text = myConfig.Config1;
  1. Saves configuration: your configuration will be saved to json file automatically when winform application's closed. Json file will be something like:
{
 "Metadata": {
 "Modified": "2019年11月11日T14:29:35.3268223+07:00"
 },
 "Configs": [
 {
 "Key": "MyObject",
 "Data": {
 "Config1": "This is a string config",
 "Config2": 123,
 }
 }
 ]
}

Advance usage

Saves immediately whenever config property changes

// Inherits from AutoNotifyPropertyChanged class and marks properties as virtual.
public class MyConfig : AutoNotifyPropertyChanged
{
 public virtual string Config1 {get;set;}
 public virtual int Config2 {get;set;}
}
// Change save mode to:
// OnChange: save immediately when config changes
// OnExit: save when app's closed
// ReadOnly: don't save
ConfigLoader.Default.SaveMode = SaveMode.OnChange;
var myConfig = ConfigLoader.Default.Get<MyConfig>();
myConfig.Config1 = "New config";// config will be saved after this call

Edits config at runtime

[ConfigClass(Description = "Describe your config here")]
public class MyConfig
{
 [Description("First string config")]
 public string Config1 { get; set; }
 [Description("Second int config")]
 public int Config2 { get; set; }
}
var myConfig = ConfigLoader.Default.Get<MyConfig>();
using (var form = new SettingsForm { Settings = myConfig })
{
 form.ShowDialog(this);
 var changed = form.SettingsChanged;
}

Edit config form

EventBus

Lightweight event aggregator/messenger for loosely coupled communication

Basic usage

  1. Defines an event which will carry data from caller to subscriber
public class MyEvent
{
 public string Data1 {get; set;}
 public int Data2 {get; set;}
}
  1. Subscribes events
class MyService
{
 MyService()
 {
 // Start subscribing incomming events (call Unregister to unsubscribe events)
 EventBus.Default.Register(this);
 }
 [Subscribe]
 private void SubscribeMethod1(MyEvent myEvent)
 {
 // do you stuff here
 }
 [Subscribe]
 private void SubscribeMethod2(MyEvent2 myEvent2)
 {
 // do you stuff here
 }
}
  1. Raises an event
// Somewhere else in your project
EventBus.Default.Post(new MyEvent {Data1 = "my data1", Data2 = 123});// SubscribeMethod1 will be called
EventBus.Default.Post(new MyEvent1 {...});// SubscribeMethod2 will be called

Advance usage

Subscribes an event in background thread

// Currently we're supporting several thread modes:
// Post: default mode, invokes subscribers immediately in current caller thread
// Thread: invokes subscribers in a new background thread if caller thread is main thread, otherwise invokes subscribers immediately in current caller thread 
// Async: Always invokes subsribers in a new background thread
// Main: Invokes subscribers in main thread (UI thread) in blocking mode
// MainOrder: Invokes subsribers in main thread (UI thread) in non-blocking mode
[Subscribe(ThreadMode = ThreadMode.Thread)]
private void WillBeCalledInBackgroundThread(MyEvent myEvent)
{
 // this stuff will be called in background thread
}

Prevents further propagation of the current event

[Subscribe]
private PostHandled CancelableSubscriber(MyEvent myEvent)
{
 // do you stuff here
 return new PostHandled {Canceled = true};
}

Returns data for caller (only supports for Post or Main ThreadMode)

// From subscribers
[Subscribe]
private PostHandled ReturnValueForCaller1(MyEvent myEvent)
{
 // do you stuff here
 return new PostHandled {Data = "any data here"};
}
[Subscribe]
private string ReturnValueForCaller2(MyEvent myEvent)
{
 // do you stuff here
 return "any data here";
}
// From caller
var results = EventBus.Default.Post(new MyEvent{...});

Keeps the last sticky event of a certain type in memory. Then the sticky event can be delivered to subscribers or queried explicitly.

// Posts a sticky event
EventBus.Default.Post(new MyEvent{...}, true);// MyEvent likes other events but it's still remaining in memory after called
EventBus.Default.Post(new MyEvent{...}, true);// this will replace the first event
// Queries a specific sticky event
var myStickyEvent = EventBus.Default.GetStickyEvent(typeof(MyEvent));
// Removes a specific sticky event
EventBus.Default.RemoveStickyEvent(myStickyEvent);

Communicates with another process uses EventBus

Client process

var eventbus = ClientEventBus.StartNew("my-eventbus");
eventbus.Post(new MyEvent{...});

Main process (ex: a windows service)

var eventbus = ServerEventBus.StartNew("my-eventbus);
eventbus.Register(this);
.....
[Subscribe]
private void ListenMyEvent(MyEvent myEvent)
{
...
}

AppCrash

Handles and reports unhandled-exception automatically

Basic usage

private AppCrash appCrash = new AppCrash(); // defines it as a global variable to prevent GC collects this.

If an unhandled-exception occurs, a crash report will be shown with notepad, the log file is also saved in CrashLogs folder. Crash report

Advance usage

Show report with a custom form.

// defines you report form
public class YourReportForm : Form, IReportWindow
{
 ....
 public void Initialize(Exception exception, string productName, string devMail)
 {
 textBox1.Text = exception.Message;
 textBox2.Text = productName;
 textBox3.Text = devMail;
 }
}
// Registers you report form
var appCrash = new AppCrash
{
 ProductName = "My product",
 DeveloperMail = "xuanson33bk@gmail.com"
};
appCrash.Register(typeof(YourReportForm));

Custom crash logs folder location

var appCrash = new AppCrash {CrashDir = @"C:\newCrashLogsDir"};

IoC

Inversion of Control Container (bases on https://github.com/grumpydev/TinyIoC)

Basic usage

// You can annotate your class by Component, Service, Repository or Controller, they are the same but for easier to understand their roles.
[Controller]
public class MyApp
{
 // Properties which are annotated with Autowired attribute will
 // be injected automatically
 [Autowired]
 public MyComponent MyComponent {get; set;}
 // myService will be injected automatically
 public MyApp(MyService myService) {...}
 ....
}
[Service]
public class MyService {....}
[Component]
public class MyComponent{....}
// Somewhere else...
// App32Context will scan the entry assembly to find classes which are annotated with Controller, Component, Repository or Service attributes.
using (var context = new App32Context())
{
 var myApp = context.Resolve<MyApp>();
 myApp.Start();
}

Advance usage

Scans classes in specific assemblies

// If you don't pass any assembly, the entry assembly will be used
using (var context = new App32Context(assembly1, assemly2, assembly3))
{
 ....
}

Creates multiple instances of components

// By default, only one instance of a component will be created (singleton mode). If you want to create a new instance of a component each time it's injected to another component, set Singleton to false
[Service(Singleton = false)]
public class MyService {....}

IConfigLoader, IEventBus and AppCrash are registered automatically so you don't need to worry about these guys

using (var context = new App32Context())
{
 var config = context.Resolve<IConfigLoader>();
 ....
}

DynamicInvoker

Manipulates on types which don't need to reference explicitly.

Basic usage

Gets type

// Gets Control class from winform namespace, if current project doesn't reference to winform, return type will be null
var type = DynamicInvoker.GetType("System.Windows.Forms", "Control");

Registers event

// Registers ApplicationExit event on Application class
var type = DynamicInvoker.GetType("System.Windows.Forms", "Application");
if (type != null)
{
 DynamicInvoker.AddEventHandler<EventHandler>(type, "ApplicationExit", Application_ApplicationExit);
}

Invokes method

// Invokes CreateControl method on Control instance
var type = DynamicInvoker.GetType("System.Windows.Forms", "Control");
if (type != null)
{
 var control = Activator.CreateInstance(type);
 DynamicInvoker.InvokeMethod(control, "CreateControl");
}

Gets or sets property value

// Gets ProductName from Application class
var type1 = DynamicInvoker.GetType("System.Windows.Forms", "Application");
if (type1 != null)
{
 var productName = DynamicInvoker.GetPropertyValue(type1, "ProductName") as string;
}
// Sets "My text" to Text property
var type2 = DynamicInvoker.GetType("System.Windows.Forms", "Control");
if (type2 != null)
{
 var control = Activator.CreateInstance(type2);
 DynamicInvoker.SetPropertyValue(control, "Text", "My text");
}

Intercomm

Inter process communication which allows processes to communicate each other and synchronize their actions

Basic usage

1 client - 1 server communication

Sender process (client)

using (var sender = new Sender("my-intercomm"))
{
 var response = await sender.SendAsync<string>("Hi server, I'm client1");
 Console.WriteLine("Response from the other process is: " + response);
}

Receiver process (server)

using (var receiver = new SingleReceiver("my-intercomm"))
{
 var request = await receiver.ReceiveAsync<string>();
 await receiver.SendAsync("Hello " + request);
}

Advantage usage

n client - 1 server communication

Setup your sender process likes the basic usage section.

Receiver process (server)

using (var receiver = new MultiReceiver("my-intercomm"))
{
 await receiver.WaitForSessionAsync(async session =>
 {
 var request = await session.ReceiveAsync<string>();
 await session.SendAsync("Hello " + request);
 });
}

Currently this library supports communicating through tcp and pipe:

  • Blackcat.Intercomm.Pipe: for pipe supported
  • Blackcat.Intercomm.Tcp: for tcp supported

About

A bundle of dotnet utilities

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

AltStyle によって変換されたページ (->オリジナル) /