Skip to content

Commit 6083dfa

Browse files
committed
Import first half of Castle Core docs from the wiki
1 parent 92e8799 commit 6083dfa

8 files changed

+418
-0
lines changed

Diff for: docs/CONTRIBUTING.md

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
The documentation is written in Markdown.
2+
3+
[Atom](https://atom.io/) is a good editor for GitHub Flavored Markdown because it has a preview window.
4+
5+
To keep the syntax consistent we use [markdownlint](https://github.com/mivok/markdownlint), please run it if you are changing
6+
a significant amount of documentation.
7+
8+
Markdownlint can be installed by running.
9+
10+
```
11+
gem install mdl
12+
```
13+
14+
Running the linter is as easy as:
15+
16+
```
17+
cd doc
18+
mdl --style=markdownlint.rb .
19+
```

Diff for: docs/README.md

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Castle Core Documentation
2+
3+
<img align="right" src="images/castle-logo.png">
4+
5+
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.
6+
7+
## DynamicProxy
8+
9+
[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).
10+
11+
## DictionaryAdapter
12+
13+
[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.
14+
15+
## Scheduler
16+
17+
[Castle Scheduler](scheduler.md) - a lightweight job scheduling service.

Diff for: docs/dictionaryadapter-customize-keys.md

+163
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
# Castle DictionaryAdapter - Customizing Adapter Keys
2+
3+
By default DictionaryAdapter will use very simple strategy when inserting/retrieving data to/from dictionary via adapter - property name becomes the key.
4+
5+
So doing:
6+
7+
```
8+
adapter.Name = "Stefan";
9+
```
10+
11+
is identical to doing
12+
13+
```csharp
14+
dictionary["Name"] = "Stefan";
15+
```
16+
17+
Same with reading
18+
19+
```csharp
20+
var name = adapter.Name;
21+
```
22+
23+
is identical to doing
24+
25+
```csharp
26+
var name = (string)dictionary["Name"];
27+
```
28+
29+
:information_source: **A word about conversion:** Well that's not entirely true. DictionaryAdapter uses a more sophisticated mechanism for conversion than just plain casting.
30+
31+
This is a fine default, but the adapter lets you customize that behavior using attributes.
32+
33+
For the examples below, lets assume the setup is as follows:
34+
35+
```csharp
36+
var dictionary = new Hashtable();
37+
var adapter = new DictionaryAdapterFactory.GetAdapter<IPerson>(dictionary);
38+
```
39+
40+
## Standard Attributes
41+
42+
Out of the box DictionaryAdapter provides set of attributes that should suffice for majority of cases.
43+
44+
### `Key` Attribute
45+
46+
If you want the property name and dictionary key to be totally unrelated you can override the default name using `KeyAttribute`.
47+
48+
```csharp
49+
public interface IPerson
50+
{
51+
[Key("PersonId")]
52+
string Name {get; set;}
53+
}
54+
```
55+
56+
Now:
57+
58+
```csharp
59+
adapter.Name == dictionary["PersonId"];
60+
```
61+
62+
### `KeyPrefix` Attribute
63+
64+
If you would like to prefix all keys in dictionary with some string use `KeyPrefixAttribute`.
65+
66+
```csharp
67+
[KeyPrefix("Person")]
68+
public interface IPerson
69+
{
70+
string Name {get; set;}
71+
}
72+
```
73+
74+
Now:
75+
76+
```csharp
77+
adapter.Name == dictionary["PersonName"];
78+
```
79+
80+
If we had more properties on the interface, they'd all get prefixed.
81+
82+
### `TypeKeyPrefix` Attribute
83+
84+
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.
85+
86+
```csharp
87+
[TypeKeyPrefix]
88+
public interface IPerson
89+
{
90+
string Name {get; set;}
91+
}
92+
```
93+
94+
Now:
95+
96+
```csharp
97+
adapter.Name == dictionary["Acme.Crm.IPerson#Name"];
98+
```
99+
100+
If we had more properties on the interface, they'd all get prefixed.
101+
102+
### `KeySubstitution` Attribute
103+
104+
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.
105+
106+
```csharp
107+
public interface IPerson
108+
{
109+
[KeySubstitution("_",".")]
110+
string Full_Name {get; set;}
111+
}
112+
```
113+
114+
Now:
115+
116+
```cs`harp
117+
adapter.Full_Name == dictionary["Full.Name"];
118+
```
119+
120+
## Creating Custom Attributes
121+
122+
Custom attributes need to implement two interfaces:
123+
124+
* `IDictionaryBehavior` - Standard base type for all DictionaryAdapter attributes. Usually you'll inherit base `DictionaryBehaviorAttribute` class and forget about it.
125+
* `IDictionaryKeyBuilder` - that's the contract for customizing the key.
126+
127+
### Example - `KeyPostfix` Attribute
128+
129+
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:
130+
131+
```csharp
132+
public interface IPerson
133+
{
134+
[KeyPostfix("Person")]
135+
string Name {get; set;}
136+
}
137+
```
138+
139+
and get:
140+
141+
```csharp
142+
adapter.Name == dictionary["NamePerson"];
143+
```
144+
145+
Simple implementation might look like this:
146+
147+
```csharp
148+
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
149+
public class KeyPostfixAttribute : DictionaryBehaviorAttribute, IDictionaryKeyBuilder
150+
{
151+
private String postfix;
152+
153+
public KeyPrefixAttribute(string keyPrefix)
154+
{
155+
this.postfix = keyPrefix;
156+
}
157+
158+
String IDictionaryKeyBuilder.GetKey(IDictionaryAdapter dictionaryAdapter, String key, PropertyDescriptor property)
159+
{
160+
return key + postfix;
161+
}
162+
}
163+
```

Diff for: docs/dictionaryadapter.md

+66
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Castle DictionaryAdapter
2+
3+
## Introduction
4+
5+
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...
6+
7+
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.
8+
9+
It can also be used with any other dictionary in any other part of your application.
10+
11+
## Hello World Example
12+
13+
Hello world example of DictionaryAdapter is just few lines of code.
14+
15+
### Using
16+
17+
After you've added a reference to `Castle.Core.dll` you need to import the following namespace:
18+
19+
```csharp
20+
using Castle.Components.DictionaryAdapter;
21+
```
22+
23+
### The Interface
24+
25+
First we just need a plain simple interface:
26+
27+
```csharp
28+
public interface IHelloWorld
29+
{
30+
string Message { get; }
31+
}
32+
```
33+
34+
### Reading
35+
36+
We can now create an adapter for the interface:
37+
38+
```csharp
39+
var dictionary = new Hashtable();
40+
var factory = new DictionaryAdapterFactory();
41+
var adapter = factory.GetAdapter<IHelloWorld>(dictionary);
42+
dictionary["Message"] = "Hello world!";
43+
Debug.Assert(adapter.Message == "Hello world!");
44+
```
45+
46+
We start with the dictionary we want to wrap with the adapter. In actual applications this would for example be http session.
47+
Then we need something to create the adapter with. Meet `DictionaryAdapterFactory`.
48+
49+
: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.
50+
51+
With the factory we create the adapter passing in the dictionary we want to wrap.
52+
53+
That's it - you can now read from the dictionary using the adapter.
54+
55+
### Writing
56+
57+
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.
58+
59+
```csharp
60+
adapter.Message = "Hello world!";
61+
Debug.Assert(dictionary["Message"] == "Hello world!");@@
62+
```
63+
64+
### See also
65+
66+
* [Customizing adapter keys](dictionaryadapter-customize-keys.md)

Diff for: docs/dynamicproxy.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# Castle DynamicProxy

Diff for: docs/images/castle-logo.png

3.71 KB
Loading

Diff for: docs/markdownlint.rb

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
all
2+
exclude_rule 'MD010' # Hard tabs - too much example code has tabs
3+
exclude_rule 'MD013' # Line length
4+
exclude_rule 'MD033' # Inline HTML - for right-aligning an image
5+
exclude_rule 'MD040' # Fenced code blocks should have a language specified

0 commit comments

Comments
 (0)