Skip to content

Commit

Permalink
初始化文档
Browse files Browse the repository at this point in the history
  • Loading branch information
kiler398 committed May 28, 2016
0 parents commit 2ed71a0
Show file tree
Hide file tree
Showing 165 changed files with 18,746 additions and 0 deletions.
73 changes: 73 additions & 0 deletions Castle/Castle.Transactions/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
Documentation on [Wiki!](https://github.com/haf/Castle.Services.Transaction/wiki)

*v3.1*

# Castle Transactions

A project for transaction management on .Net and mono.

## Quick Start

You have a few major options. The first option is to install the Windsor integration:

`install-package Castle.Facilities.AutoTx`,

- -> Castle.Facilities.AutoTx
- -> Castle.Transactions.IO
- -> Castle.Transactions
- -> Castle.Core

another option is if you're using Autofac:

`install-package Castle.Transactions.Autofac`

- -> Autofac ~> 2.5
- -> Castle.Transactions.Autofac
- -> Castle.Transactions.IO
- -> Castle.Transactions
- -> Castle.Core

another option is that you only care about the transactions API as a stand-alone:

`install-package Castle.Transactions` -> Castle.Core

another option is that you care about the transactions API + transactional NTFS:

`install-package Castle.Transactions.IO`

- -> Castle.Transactions
- -> Castle.IO
- -> Castle.Core

### Castle Transactions

The original project that manages transactions.

#### Main Features

* Regular Transactions (+`System.Transactions` interop) - allows you to create transactions with a nice API
* Dependent Transactions - allows you to fork dependent transactions automatically by declarative programming: `[Transaction(Fork=true)]`
* Transaction Logging - A trace listener in namespace `Castle.Transactions.Logging`, named `TraceListener`.
* Retry policies for transactions

#### Main Interfaces

- `ITransactionManager`:
- *default implementation is `TransactionManager`*
- keeps tabs on what transaction is currently active
- coordinates parallel dependent transactions
- keep the light weight transaction manager (LTM) happy on the CLR

### Castle Transactions IO

A project for adding a transactional file system to the mix!

#### Main Features

* Provides an `Castle.IO.IFileSystem` implementation that adds transactionality to common operations.



### Remarks

See also the [Castle.IO](https://github.com/haf/Castle.IO) project.
19 changes: 19 additions & 0 deletions Castle/Core/CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
The documentation is written in Markdown.

[Atom](https://atom.io/) is a good editor for GitHub Flavored Markdown because it has a preview window.

To keep the syntax consistent we use [markdownlint](https://github.com/mivok/markdownlint), please run it if you are changing
a significant amount of documentation.

Markdownlint can be installed by running.

```
gem install mdl
```

Running the linter is as easy as:

```
cd doc
mdl --style=markdownlint.rb .
```
17 changes: 17 additions & 0 deletions Castle/Core/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Castle Core Documentation

<img align="right" src="images/castle-logo.png">

Other than the three main projects, Castle consists of a whole range of smaller, but very useful libraries that you can take advantage of in your application.

## DynamicProxy

[Castle DynamicProxy](dynamicproxy.md) - a lightweight, lightning fast framework for generating proxies on the fly, used extensively by multiple projects within Castle (Windsor, MonoRail) and outside of it (NHibernate, Rhino Mocks, AutoMapper and many others).

## DictionaryAdapter

[Castle DictionaryAdapter](dictionaryadapter.md) - on the fly generates strongly typed wrappers around untyped dictionaries, or chunks of XML (like config file), optionally adding support for change notification, cancelation, error notification and other features.

## Scheduler

[Castle Scheduler](scheduler.md) - a lightweight job scheduling service.
163 changes: 163 additions & 0 deletions Castle/Core/dictionaryadapter-customize-keys.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
# Castle DictionaryAdapter - Customizing Adapter Keys

By default DictionaryAdapter will use very simple strategy when inserting/retrieving data to/from dictionary via adapter - property name becomes the key.

So doing:

```
adapter.Name = "Stefan";
```

is identical to doing

```csharp
dictionary["Name"] = "Stefan";
```

Same with reading

```csharp
var name = adapter.Name;
```

is identical to doing

```csharp
var name = (string)dictionary["Name"];
```

:information_source: **A word about conversion:** Well that's not entirely true. DictionaryAdapter uses a more sophisticated mechanism for conversion than just plain casting.

This is a fine default, but the adapter lets you customize that behavior using attributes.

For the examples below, lets assume the setup is as follows:

```csharp
var dictionary = new Hashtable();
var adapter = new DictionaryAdapterFactory.GetAdapter<IPerson>(dictionary);
```

## Standard Attributes

Out of the box DictionaryAdapter provides set of attributes that should suffice for majority of cases.

### `Key` Attribute

If you want the property name and dictionary key to be totally unrelated you can override the default name using `KeyAttribute`.

```csharp
public interface IPerson
{
[Key("PersonId")]
string Name {get; set;}
}
```

Now:

```csharp
adapter.Name == dictionary["PersonId"];
```

### `KeyPrefix` Attribute

If you would like to prefix all keys in dictionary with some string use `KeyPrefixAttribute`.

```csharp
[KeyPrefix("Person")]
public interface IPerson
{
string Name {get; set;}
}
```

Now:

```csharp
adapter.Name == dictionary["PersonName"];
```

If we had more properties on the interface, they'd all get prefixed.

### `TypeKeyPrefix` Attribute

If you would like to prefix all keys in dictionary with full name of the interface use `TypeKeyPrefixAttribute`. This is especially useful when you have multiple adapters over common dictionary and you want to avoid one overriding another.

```csharp
[TypeKeyPrefix]
public interface IPerson
{
string Name {get; set;}
}
```

Now:

```csharp
adapter.Name == dictionary["Acme.Crm.IPerson#Name"];
```

If we had more properties on the interface, they'd all get prefixed.

### `KeySubstitution` Attribute

If you would like to replace certain characters in your key use `TypeKeyPrefixAttribute`. This is especially useful when you want to use certain characters in your key, that are not legal in C# names. You can set the attribute at interface level, or at property level.

```csharp
public interface IPerson
{
[KeySubstitution("_",".")]
string Full_Name {get; set;}
}
```

Now:

```cs`harp
adapter.Full_Name == dictionary["Full.Name"];
```
## Creating Custom Attributes
Custom attributes need to implement two interfaces:
* `IDictionaryBehavior` - Standard base type for all DictionaryAdapter attributes. Usually you'll inherit base `DictionaryBehaviorAttribute` class and forget about it.
* `IDictionaryKeyBuilder` - that's the contract for customizing the key.
### Example - `KeyPostfix` Attribute
As an example let's assume we want to create attribute that adds common postfix to the property keys, so that we can use it like follows:
```csharp
public interface IPerson
{
[KeyPostfix("Person")]
string Name {get; set;}
}
```

and get:

```csharp
adapter.Name == dictionary["NamePerson"];
```

Simple implementation might look like this:

```csharp
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class KeyPostfixAttribute : DictionaryBehaviorAttribute, IDictionaryKeyBuilder
{
private String postfix;

public KeyPrefixAttribute(string keyPrefix)
{
this.postfix = keyPrefix;
}

String IDictionaryKeyBuilder.GetKey(IDictionaryAdapter dictionaryAdapter, String key, PropertyDescriptor property)
{
return key + postfix;
}
}
```
66 changes: 66 additions & 0 deletions Castle/Core/dictionaryadapter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# Castle DictionaryAdapter

## Introduction

DictionaryAdapter is a lightweight tool that on the fly generates strongly typed wrappers on top of `IDictionary` (and its generic brother) type. Not only that, but it also has some other capabilities like support for `INotifyPropertyChanged`, editability, error handling, etc...

It is extremely useful in the context of web applications, as there are many untyped dictionaries in use, such as `Session`, `Form`, `QueryString`, `Context.Items`, and MonoRail's `PropertyBag` and `Flash`. It can also wrap settings from `app.settings`/`web.settings` file.

It can also be used with any other dictionary in any other part of your application.

## Hello World Example

Hello world example of DictionaryAdapter is just few lines of code.

### Using

After you've added a reference to `Castle.Core.dll` you need to import the following namespace:

```csharp
using Castle.Components.DictionaryAdapter;
```

### The Interface

First we just need a plain simple interface:

```csharp
public interface IHelloWorld
{
string Message { get; }
}
```

### Reading

We can now create an adapter for the interface:

```csharp
var dictionary = new Hashtable();
var factory = new DictionaryAdapterFactory();
var adapter = factory.GetAdapter<IHelloWorld>(dictionary);
dictionary["Message"] = "Hello world!";
Debug.Assert(adapter.Message == "Hello world!");
```

We start with the dictionary we want to wrap with the adapter. In actual applications this would for example be http session.
Then we need something to create the adapter with. Meet `DictionaryAdapterFactory`.

:information_source: **Reuse `DictionaryAdapterFactory`:** The `DictionaryAdapterFactory` is like DynamicProxy's `ProxyGenerator` - you normally wouldn't just create it on the spot each time you need an adapter. You should strive to reuse it as much as possible, so it's a good idea to make it a singleton.

With the factory we create the adapter passing in the dictionary we want to wrap.

That's it - you can now read from the dictionary using the adapter.

### Writing

The interface in the example above had just a getter for its sole property, but if it also had a setter we could write to it as well.

```csharp
adapter.Message = "Hello world!";
Debug.Assert(dictionary["Message"] == "Hello world!");@@
```

### See also

* [Customizing adapter keys](dictionaryadapter-customize-keys.md)
46 changes: 46 additions & 0 deletions Castle/Core/dynamicproxy-fine-grained-control.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Use *proxy generation hooks* and *interceptor selectors* for fine grained control

Does your interceptor look like this?

```csharp
public void Intercept(IInvocation invocation)
{
if (invocation.TargetType != typeof(Foo))
{
invocation.Proceed();
return;
}

if (invocation.Method.Name != "Bar")
{
invocation.Proceed();
return;
}

if (invocation.Method.GetParameters().Length != 3)
{
invocation.Proceed();
return;
}

DoSomeActualWork(invocation);
}
```

## Solution

If they do this often means you're doing something wrong. Move the decisions to `IProxyGenerationHook` and `IInterceptorSelector`.

* Do I ever want to intercept this method? If the answer is no, use proxy generation hook to filter it out of methods to proxy.

> Notice that due to bug in DynamicProxy 2.1, if you choose not to proxy method on interface proxy, you will get an exception. Workaround for this is to say you want to intercept the method, and then use interceptor selector to return no interceptors for the method. This bug is fixed in DynamicProxy 2.2
* If I do want to intercept this method, which interceptors do I want to use? Do I need all of them? Do I need just a single one? Use interceptor selector to control this.

## When **not to** do this

On the other hand, remember that as every feature this one is also a double edged sword. Too liberal use of proxy generation hooks and interceptor selectors may greatly decrease efficiency of proxy type caching, which may hurt your performance. As always think how much control you need and what the implications on caching will be. Sometimes single if on top of your interceptor is lesser evil than increasing number of proxies required tenfold. As always – use the profiler in scenarios that mimic your production scenarios as closely as possible to check which option is the best for you.

## See also

* [SRP applies to interceptors](dynamicproxy-srp-applies-to-interceptors.md)
Loading

0 comments on commit 2ed71a0

Please sign in to comment.