-
1.开篇介绍
-
2.尽量使用Lambda匿名函数调用代替反射调用(走进声明式设计)
-
3.被忽视的特性(Attribute)设计方式
-
4.扩展方法让你的对象如虎添翼(要学会使用扩展方法的设计思想)
-
5.别怕Static属性(很多人都怕Static在Service模式下的设计,其实要学会使用线程本地存储(ThreadStatic))
-
6.泛型的协变与逆变(设计架构接口(Interface)时要时刻注意对象的协变、逆变)
-
7.使用泛型的类型推断(还在为参数类型烦恼吗)
-
8.链式编程(设计符合大脑思维习惯的处理流程)
-
8.1.链式编程(多条件(方法碎片化)调用
-
-
9.部分类、部分方法的使用(扩大设计范围)
1.】开篇介绍
2.】尽量使用委托调用代替反射调用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
/*==============================================================================
* Author:深度训练
* Create time: 2013-07-28
* Blog Address:http://www.cnblogs.com/wangiqngpei557/
* Author Description:特定领域软件工程实践;
*==============================================================================*/
using
System;
using
System.Collections.Generic;
using
System.Linq.Expressions;
using
System.Linq;
using
Infrastructure.Common.Cache;
using
Infrastructure.Common.Validator;
namespace
ConsoleApplication1.DomainModel
{
/// <summary>
/// Order.
/// </summary>
[EntityCache(10,
true
)]
[EntityValidator(ValidatorOperationType.All)]
public
class
Order
{
/// <summary>
/// Order code.
/// </summary>
public
string
OrderCode {
get
;
set
; }
/// <summary>
/// Items filed.
/// </summary>
private
List<Item> items =
new
List<Item>();
/// <summary>
/// Gets items .
/// </summary>
public
IEnumerable<Item> Items {
get
{
return
items; } }
/// <summary>
/// Submit order date.
/// </summary>
public
DateTime SubmitDate {
get
;
set
; }
/// <summary>
/// Mark <see cref="DomainModel.Order"/> Instance.
/// </summary>
/// <param name="orderCode">Order code. </param>
public
Order(
string
orderCode)
{
this
.OrderCode = orderCode;
}
/// <summary>
/// Sum items prices.
/// </summary>
/// <param name="itemUsingType">item type.</param>
/// <returns>prices .</returns>
public
double
SumPrices(
int
itemUsingType)
{
double
resultPrices = 0.00;
var
currentItems = items.GroupBy(item => item.ItemUsingType).Single(
group
=>
group
.Key == itemUsingType);
if
(currentItems.Count() > 0)
{
foreach
(
var
item
in
currentItems)
{
resultPrices += item.Price;
}
}
return
resultPrices;
}
/// <summary>
/// Add item to order.
/// </summary>
/// <param name="item">Item.</param>
/// <returns>bool.</returns>
public
bool
AddItem(Item item)
{
if
(!item.ItemCode.Equals(
string
.Empty))
{
this
.items.Add(item);
return
true
;
}
return
false
;
}
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
/*==============================================================================
* Author:深度训练
* Create time: 2013-07-28
* Blog Address:http://www.cnblogs.com/wangiqngpei557/
* Author Description:特定领域软件工程实践;
*==============================================================================*/
using
System;
namespace
ConsoleApplication1.DomainModel
{
/// <summary>
/// Order item.
/// </summary>
public
class
Item
{
/// <summary>
/// Item code.
/// </summary>
public
Guid ItemCode {
get
;
set
; }
/// <summary>
/// Item price.
/// </summary>
public
float
Price {
get
;
set
; }
/// <summary>
/// Item using type.
/// </summary>
public
int
ItemUsingType {
get
;
set
; }
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
using
System;
using
Microsoft.VisualStudio.TestTools.UnitTesting;
using
NSubstitute;
namespace
ConsoleApplication.UnitTest
{
using
ConsoleApplication1.DomainModel;
/// <summary>
/// Order unit test.
/// </summary>
[TestClass]
public
class
DomainModelOrderUnitTest
{
/// <summary>
/// Order sumprices using type 1 test.
/// </summary>
[TestMethod]
public
void
DomainModelOrderUnitTest_SumPrices_ItemUsingTypeIs1_UnitTest()
{
Order testOrder =
new
Order(Guid.NewGuid().ToString());
testOrder.AddItem(
new
Item() { ItemCode = Guid.NewGuid(), ItemUsingType = 1, Price = 10.0F });
testOrder.AddItem(
new
Item() { ItemCode = Guid.NewGuid(), ItemUsingType = 1, Price = 15.0F });
testOrder.AddItem(
new
Item() { ItemCode = Guid.NewGuid(), ItemUsingType = 2, Price = 20.0F });
testOrder.AddItem(
new
Item() { ItemCode = Guid.NewGuid(), ItemUsingType = 2, Price = 30.0F });
double
result = testOrder.SumPrices(1);
Assert.AreEqual(result, 25.0F);
}
/// <summary>
/// Order sumprices using type is 2 test.
/// </summary>
[TestMethod]
public
void
DomainModelOrderUnitTest_SumPrices_ItemUsingTypeIs2_UnitTest()
{
Order testOrder =
new
Order(Guid.NewGuid().ToString());
testOrder.AddItem(
new
Item() { ItemCode = Guid.NewGuid(), ItemUsingType = 1, Price = 10.0F });
testOrder.AddItem(
new
Item() { ItemCode = Guid.NewGuid(), ItemUsingType = 1, Price = 15.0F });
testOrder.AddItem(
new
Item() { ItemCode = Guid.NewGuid(), ItemUsingType = 2, Price = 20.0F });
testOrder.AddItem(
new
Item() { ItemCode = Guid.NewGuid(), ItemUsingType = 2, Price = 30.0F });
double
result = testOrder.SumPrices(2);
Assert.AreEqual(result, 50.0F);
}
}
}
|
1
2
3
4
5
6
7
8
9
|
using
System;
namespace
Infrastructure.Common
{
public
interface
IBusinessService
{
void
SendBusinessData(
object
callAuthor,
string
methodName,
object
parameterInstance);
void
SendBusinessData<P>(Func<P,
object
> callFun, P parameter);
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
using
System;
using
System.Reflection;
using
System.Linq;
using
System.Linq.Expressions;
namespace
Infrastructure.Common
{
/// <summary>
/// Business service .
/// </summary>
public
class
BusinessService : IBusinessService
{
/// <summary>
/// Send service data interface .
/// </summary>
private
ISendServiceData sendService;
/// <summary>
/// Mark <see cref="Infrastructure.Common.ISendServiceData"/> instance.
/// </summary>
/// <param name="sendService"></param>
public
BusinessService(ISendServiceData sendService)
{
this
.sendService = sendService;
}
/// <summary>
/// Send business data to service interface.
/// </summary>
/// <param name="callAuthor">Object author.</param>
/// <param name="methodName">Method name.</param>
/// <param name="parameterInstance">Method call parameter.</param>
public
void
SendBusinessData(
object
callAuthor,
string
methodName,
object
parameterInstance)
{
object
result =
callAuthor.GetType().GetMethod(methodName).Invoke(callAuthor,
new
object
[] { parameterInstance });
if
(result !=
null
)
{
sendService.Send(result);
}
}
/// <summary>
/// Send business data to service interface.
/// </summary>
/// <typeparam name="P"></typeparam>
/// <param name="callFun"></param>
/// <param name="parameter"></param>
public
void
SendBusinessData<P>(Func<P,
object
> callFun, P parameter)
{
object
result = callFun(parameter);
if
(result !=
null
)
{
sendService.Send(result);
}
}
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
|
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Text;
using
System.Threading.Tasks;
namespace
Infrastructure.Common
{
public
interface
ISendServiceData
{
void
Send(
object
sendObject);
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
using
System;
using
Microsoft.VisualStudio.TestTools.UnitTesting;
using
Infrastructure.Common;
using
ConsoleApplication1.DomainModel;
using
NSubstitute;
namespace
Infrastructure.Common.UnitTest
{
[TestClass]
public
class
InfrastructureCommonBusinsessServiceUnitTest
{
[TestMethod]
public
void
InfrastructureCommonBusinsessServiceUnitTest_BusinessService_SendBusinessData()
{
Order order =
new
Order(Guid.NewGuid().ToString());
order.AddItem(
new
Item() { ItemCode = Guid.NewGuid(), ItemUsingType = 1, Price = 10.0F });
order.AddItem(
new
Item() { ItemCode = Guid.NewGuid(), ItemUsingType = 1, Price = 15.0F });
order.AddItem(
new
Item() { ItemCode = Guid.NewGuid(), ItemUsingType = 2, Price = 20.0F });
order.AddItem(
new
Item() { ItemCode = Guid.NewGuid(), ItemUsingType = 2, Price = 30.0F });
ISendServiceData mockISendServiceData = Substitute.For<ISendServiceData>();
object
sendresult =
null
;
mockISendServiceData.When(isend => isend.Send(Arg.Any<
object
>())).Do(callinfo => sendresult = callinfo.Arg<
object
>());
BusinessService testService =
new
BusinessService(mockISendServiceData);
testService.SendBusinessData(order,
"SumPrices"
, 1);
Assert.AreEqual((
double
)sendresult, 25);
}
[TestMethod]
public
void
InfrastructureCommonBusinsessServiceUnitTest_BusinessService_SendBusinessDataGen()
{
Order order =
new
Order(Guid.NewGuid().ToString());
order.AddItem(
new
Item() { ItemCode = Guid.NewGuid(), ItemUsingType = 1, Price = 10.0F });
order.AddItem(
new
Item() { ItemCode = Guid.NewGuid(), ItemUsingType = 1, Price = 15.0F });
order.AddItem(
new
Item() { ItemCode = Guid.NewGuid(), ItemUsingType = 2, Price = 20.0F });
order.AddItem(
new
Item() { ItemCode = Guid.NewGuid(), ItemUsingType = 2, Price = 30.0F });
ISendServiceData mockISendServiceData = Substitute.For<ISendServiceData>();
object
sendresult =
null
;
mockISendServiceData.When(isend => isend.Send(Arg.Any<
object
>())).Do(callinfo => sendresult = callinfo.Arg<
object
>());
BusinessService testService =
new
BusinessService(mockISendServiceData);
testService.SendBusinessData<Order>(ord => {
return
ord.SumPrices(1); }, order);
Assert.AreEqual((
double
)sendresult, 25);
}
}
}
|
3】被忽视的特性(Attribute)设计方式
1
2
3
4
5
6
7
|
/// <summary>
/// Order.
/// </summary>
[EntityCache(10,
true
)]
[EntityValidator(ValidatorOperationType.All)]
public
class
Order
{}
|
1
2
3
4
5
6
7
8
9
|
Codeusing System;
namespace
Infrastructure.Common
{
[AttributeUsage(AttributeTargets.Class)]
public
abstract
class
EntityOperation : Attribute
{
protected
EntityOperation NextOperation {
get
;
set
; }
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Text;
using
System.Threading.Tasks;
namespace
Infrastructure.Common.Cache
{
[AttributeUsage(AttributeTargets.Class)]
public
class
EntityCache : EntityOperation
{
public
EntityCache(
int
cacheTime,
bool
IsEnable)
{
this
.ExpireTime = cacheTime;
}
public
int
ExpireTime {
get
;
set
; }
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
using
System;
using
System.Collections.Generic;
using
System.Linq;
using
System.Text;
using
System.Threading.Tasks;
namespace
Infrastructure.Common.Validator
{
public
enum
ValidatorOperationType
{
Insert,
Delete,
Update,
Select,
All
}
[AttributeUsage(AttributeTargets.Class)]
public
class
EntityValidator : EntityOperation
{
public
EntityValidator(ValidatorOperationType validatorType)
{
}
}
}
|
4】扩展方法让你的对象如虎添翼(要学会使用扩展方法的设计思想)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
namespace
DomainModelBehavior.Order.ShippingBehavior
{
using
ConsoleApplication1.DomainModel;
public
static
class
OrderBehavior
{
public
static
Order TaxRate(
this
Order order)
{
return
order;
}
}
}
namespace
DomainModelBehavior.Order.ShoppingCart
{
using
ConsoleApplication1.DomainModel;
public
static
class
OrderBehavior
{
public
static
Order Inventory(
this
Order order)
{
return
order;
}
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
using
System;
namespace
ConsoleApplication1
{
using
DomainModelBehavior.Order.ShoppingCart;
class
Program
{
static
void
Main(
string
[] args)
{
DomainModel.Order order =
new
DomainModel.Order(Guid.NewGuid().ToString());
order.Inventory();
}
}
}
|
5】别怕Static属性(很多人都怕Static在Service模式下的设计,其实要学会使用线程本地存储(ThreadStatic))
1
2
3
4
5
|
/// <summary>
/// 数据源的操作
/// </summary>
[ThreadStatic]
private
static
IDataSourceOperation datasourceoperation = IDataSourceOperationFactory.Create();
|
6】泛型的协变与逆变(设计架构接口(Interface)时要注意对象的协变、逆变)
1
2
|
List<Apple> apples =
new
List<Apple>();
List<Item> items = apples;
|
1
2
|
List<Apple> apples =
new
List<Apple>();
IEnumerable<Item> items = apples;
|
7】使用泛型的类型推断(还在为参数类型烦恼吗)
1
2
3
4
5
6
7
|
List<Item> items =
new
List<Item>();
items.Add(
new
Item() { ItemCode = Guid.NewGuid(), ItemUsingType = 1, Price = 20 });
items.Add(
new
Item() { ItemCode = Guid.NewGuid(), ItemUsingType = 1, Price = 20 });
items.Add(
new
Item() { ItemCode = Guid.NewGuid(), ItemUsingType = 1, Price = 20 });
items.Add(
new
Item() { ItemCode = Guid.NewGuid(), ItemUsingType = 1, Price = 20 });
items.Where<Item>(item => item.ItemUsingType == 1);
items.Where(item=>item.ItemUsingType==1);
|
1
|
public
static
IEnumerable<TSource> Where<TSource>(
this
IEnumerable<TSource> source, Func<TSource,
bool
> predicate);
|
8】链式编程(设计符合大脑思维习惯的处理流程)
8.1】链式编程(多条件(方法碎片化)调用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
using
System.Collections.Generic;
namespace
ConsoleApplication1
{
public
static
class
DtoValidator
{
public
static
IEnumerable<TSource> IsNull<TSource>(
this
IEnumerable<TSource> tList)
{
return
tList;
}
public
static
IEnumerable<TSource> IsLength<TSource>(
this
IEnumerable<TSource> tList,
int
max)
{
return
tList;
}
public
static
IEnumerable<TResult> End<TResult>(
this
IEnumerable<
object
> tList, IEnumerable<TResult> result)
{
result =
new
List<TResult>();
return
result;
}
}
}
|
1
2
3
|
List<Order> orderList =
null
;
List<Dto.OrderInfoDto> dtoList =
new
List<Dto.OrderInfoDto>();
dtoList.IsNull().IsLength(3).End(orderList);
|