Skip to content
This repository was archived by the owner on Sep 7, 2021. It is now read-only.

Commit 6a20a39

Browse files
committed
update readme
1 parent 68e6d35 commit 6a20a39

File tree

1 file changed

+223
-1
lines changed

1 file changed

+223
-1
lines changed

README.md

Lines changed: 223 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,223 @@
1-
# Newbe.ObjectVisitor
1+
# Newbe.ObjectVisitor
2+
3+
You can visit all properties about your class or struct by this lib with high performance as you visit properties in hard coding way.
4+
5+
For example, here is object in your code.
6+
7+
```cs
8+
var order = new OrderInfo();
9+
```
10+
11+
And, you want to print all properties of the order.
12+
13+
```cs
14+
for(var pInfo in typeof(OrderInfo).GetProperties())
15+
{
16+
Console.Writeline($"{pInfo.Name}: {pInfo.GetValue(order)}");
17+
}
18+
```
19+
20+
By using this lib, you can handle it in this way:
21+
22+
```cs
23+
// call .V what is a static extension method
24+
// you get a visitor object for order
25+
var visitor = order.V();
26+
27+
visitor.ForEach(context=>{
28+
var name = context.Name;
29+
var value = context.Value;
30+
Console.Writeline($"{name}: {value}");
31+
}).Run();
32+
33+
// you can also make it in one line
34+
order.V().ForEach(c=> Console.Writeline($"{c.Name}: {c.Value}")).Run();
35+
```
36+
37+
"Why I need this?"
38+
39+
- It is faster. This lib impletment with [Expression Trees](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/expression-trees/) that cost 1/10 time as in Reflection way.
40+
- It is readable. This lib can generate a lambda func to handle the code flow you create that just as your hard coding without reflection.
41+
- It is extendable. If you can visit all properties of a object in easy way, you can validate them as you wish, mask some value if there are something sensitive,
42+
43+
## Status
44+
45+
Planning. This project is in planning. All you can see below is in the plan.
46+
47+
## API (plan)
48+
49+
```cs
50+
var o = new Yueluo();
51+
52+
using Newbe.ObjectVisitor;
53+
54+
// V is a static extension method
55+
var visitor = o.V();
56+
57+
// create visitor from factory method
58+
var visitor = ObjectVisitorFactory.Create(typeof(Yueluo));
59+
60+
// this is the most simple structure about this lib
61+
// there are Name, Value, PropertyInfo, SourceObj, SourceObjType and etc in the context
62+
o.V().ForEach((context)=>{}).Run();
63+
64+
// you can modify value if return a new value
65+
o.V().ForEach((context)=>context.Value.SubString(0,1)).Run();
66+
67+
// get debug info about expression now
68+
var debugInfo = o.V().ForEach((context)=>{}).GetDebugInfo();
69+
70+
// generate code in C# as a string about expression now
71+
var code = o.V().ForEach((context)=>{}).GenerateCode();
72+
73+
// generate a lambda func
74+
var func = o.V().ForEach((context)=>{}).GetLambda();
75+
76+
// foreach properties with specified type
77+
o.V().ForEach<string>((context)=>{}).Run();
78+
79+
// using linq to filter
80+
o.V().AsEnumerable().Where((context)=>context.Name == "YueLuo").ForEach((context)=>{}).Run();
81+
82+
// suppending visiting sub object
83+
o.V().SuppendSubObject().ForEach((context)=>{}).Run();
84+
85+
// suppending visiting enumerable object
86+
o.V().SuppendEnumerable().ForEach((context)=>{}).Run();
87+
88+
89+
/**
90+
sample to join all properties to string
91+
*/
92+
var sb = new StringBuilder();
93+
o.V().ForEach((context)=>{
94+
sb.Append(context.Name);
95+
sb.Append(context.Value);
96+
sb.Append(Enviroment.Newline);
97+
}).Run();
98+
var s = sb.ToString();
99+
100+
// quick style for above
101+
var s = o.V().FormatString();
102+
103+
// Deconstruct as C# 7 but more flexible
104+
var destructor1 = Destructor<Yueluo>
105+
.Property(x=>x.Name)
106+
.Property(x=>x.Age)
107+
108+
var destructor2 = Destructor<Yueluo>
109+
.Property(x=>x.Name)
110+
.Property(x=>(long)x.Age)
111+
112+
var destructor3 = Destructor<Yueluo>
113+
.Property(x=>x.Name)
114+
.Property(x=>x.NickName)
115+
.Property(x=>x.Age)
116+
117+
var (name, age) = o.V().Destruct(destructor1).Run();
118+
var (name, ageInLong) = o.V().Destruct(destructor2).Run();
119+
var (name, nickName, age) = o.V().Destruct(destructor3).Run();
120+
121+
// namespace for operation with collections
122+
using Newbe.ObjectVisitor.Collections;
123+
124+
/**
125+
collect properties into a dictionary
126+
*/
127+
128+
var dic1 = o.V().CollectAsDictionary().Run();
129+
// quick style for above
130+
var dic1 = o.V().ToDictionary();
131+
132+
/**
133+
apply value from a dictionary to object
134+
*/
135+
o.V().ApplyFromDictionary(dic).Run();
136+
// quick style for above
137+
o.V().FromDictionary(dic);
138+
139+
140+
// namespace for data validation
141+
using Newbe.ObjectVisitor.Validation;
142+
143+
// create rule to validation
144+
var rule = ValidateRule<Yueluo>
145+
.GetBuilder()
146+
.Property(x=>x.Name).Required().Length(2,10)
147+
.Property(x=>x.Age).Range(0, int.MaxValue)
148+
.Property(x=>x.Password).Validate(value=>ValidatePassword(value))
149+
.Property(x=>x.Level).Validate(value=>value + 1 >= 0)
150+
.Build();
151+
152+
o.V().Validate(rule).Run();
153+
o.Validate(rule);
154+
155+
156+
// validate data in flunet api
157+
// attribute-based enabled by default
158+
o.V().Validate(v=>
159+
v
160+
.Property(x=>x.Name).Required().Length(2,10)
161+
.Property(x=>x.Age).Range(0, int.MaxValue)
162+
.Property(x=>x.Password).Validate(value=>ValidatePassword(value))
163+
.Property(x=>x.Level).Validate(value=>value + 1 >= 0)
164+
).Run();
165+
166+
// suppending attribute-based validation
167+
o.V().SuppendAttributeValidation()
168+
.Validate(v=>
169+
v
170+
.Property(x=>x.Name).Required().Length(2,10)
171+
.Property(x=>x.Age).Range(0, int.MaxValue)
172+
.Property(x=>x.Password).Validate(value=>ValidatePassword(value))
173+
.Property(x=>x.Level).Validate(value=>value + 1 >= 0)
174+
).Run();
175+
176+
// suppending sub-object validation
177+
// validate whole object
178+
o.V().SuppendSubObject()
179+
.SuppendAttributeValidation()
180+
.Validate(v=>
181+
v
182+
.Validate(x=>x.NewPassword == x.OldPassword)
183+
.Validate(x=>ValidateFormDb(x))
184+
.Property(x=>x.Name).Required().Length(2,10)
185+
.Property(x=>x.Age).Range(0, int.MaxValue)
186+
.Property(x=>x.Age).If(x=>x.Name == "123").Range(0, int.MaxValue)
187+
.Property(x=>x.Password).Validate(value=>ValidatePassword(value))
188+
.Property(x=>x.Level).Validate(value=>value + 1 >= 0)
189+
).Run();
190+
191+
// namespace for Task
192+
using Newbe.ObjectVisitor.Task;
193+
194+
// async way
195+
await o.V().ForEachAsync((context)=>{}).RunAsync();
196+
197+
// controlling concurrency
198+
await o.V().ForEachAsync((context)=>{}).WhenAsync(tasks=>Task.WhenAll(tasks)).RunAsync();
199+
200+
// namespace for Microsoft.Extensions.DependencyInjection
201+
using Newbe.ObjectVistory.DepencyInjection;
202+
203+
// inject services to the properties of this object
204+
this.V().ForEach(context=>this.ServiceProvider.GetService(context.PropertyInfo.PorpertyType)).Run();
205+
206+
// quick style for above
207+
this.V().PropertyInject(this.ServiceProvider);
208+
209+
```
210+
211+
## Benchmark
212+
213+
TODO
214+
215+
visit properties vs Reflection vs Directly
216+
217+
validate vs FluentValidation
218+
219+
mapper vs AutoMapper
220+
221+
## Stargazers over time
222+
223+
[![Stargazers over time](https://starchart.cc/newbe36524/Newbe.ObjectVisitor.svg)](https://starchart.cc/newbe36524/Newbe.ObjectVisitor)

0 commit comments

Comments
 (0)