Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
W
WSCF
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
潘栩锋
WSCF
Commits
b7320a4a
Commit
b7320a4a
authored
May 22, 2021
by
潘栩锋
🚴
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
添加更多说明
parent
6f530842
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
222 additions
and
5 deletions
+222
-5
README.md
README.md
+82
-1
MainWindow.xaml.cs
WSCF.Test.Client/MainWindow.xaml.cs
+4
-1
IFooService.cs
WSCF.Test/IService/IFooService.cs
+75
-0
WsProxy.cs
WSCF.Test/Server.WsProxy/WsProxy.cs
+1
-1
Foo.cs
WSCF.Test/Server/Foo.cs
+31
-0
FooServiceClient.cs
WSCF.Test/ServiceClient/FooServiceClient.cs
+29
-2
No files found.
README.md
View file @
b7320a4a
# WSCF
# WSCF
WSCF (WebSocket Communication Foundation) 就是 抄 微软的WCF, 但有 推送功能。
WSCF (WebSocket Communication Foundation) 就是 抄 微软的WCF, 但有 推送功能。
\ No newline at end of file
# 1. 项目描述
**WSCF**
是项目
<br>
**WSCF.Test**
项目测试 库
<br>
**WSCF.Test.Client**
测试客户端
<br>
**WSCF.Test.Server**
测试服务器
<br>
<br>
<br>
<br>
<br>
# 2. 使用方法
1.
定义服务接口 IXXXService
//WSCF.Test/IService/IFooService.cs
2.
在服务器中,创建 类 XXX 实现 IXXXService 接口
//WSCF.Test/Server/Foo.cs
3.
在服务器中,
//WSCF.Test/Server.WsProxy/WsProxy.cs
```
csharp
wssv
=
new
WebSocketServer
(
$"ws://
{
addr
}
/"
);
wssv
.
AddWebSocketService
<
Reflect_Proxy
>(
"/Foo"
,
(
wsproxy
)
=>
{
//IFooService 服务接口, foo 继承IFooService的类Foo 的对象
wsproxy
.
Init
(
typeof
(
IFooService
),
foo
);
});
//如果有多个服务,就继续 wssv.AddWebSocketService<Reflect_Proxy>
this
.
wssv
.
Start
();
```
4.
在客户端中
创建 类 XXXServiceClient 实现 IXXXService 接口
//WSCF.Test/ServiceClient/FooServiceClient.cs
最后使用
```
csharp
//后面的 "foo" 是连接的名字,对应 地址 { Addr = "127.0.0.1:5540", ConnName = "foo" }
// WSCF.FObjServiceClientManager 负责维护这个地址列表
Foo
=
new
WSCF
.
Test
.
ServiceClient
.
FooServiceClient
(
"Foo"
,
true
,
"foo"
);
```
<br>
<br>
<br>
<br>
# 3. 描述
服务代理 它还另一个版本 在项目 FObjBase.Reflect
1.
如果代理的对象为 INotifyPropertyChanged, 对象内的 property 改变,能推送给客户端(
[
JsonIgnore
]
除外);
2.
代理的对象不为INotifyPropertyChanged, 但 对象内的 property
+ 是 [PropertyPush],
+ 且是 INotifyPropertyChanged,
+ 且 只能是get,不能有set
那这个 property 内的 子property 改变,也会推送给 客户端 且 子property 是
[
PropertyPush
]
,会继续向下全部注册 PropertyChanged, 也推送给 客户端;
3.
客户端 可以通过 Call(.....) 调用 服务 的function, function返回的内容,需要通过
[
Call(...)
]
定义; 且function 必须是
```
csharp
void
function
(
object
param1
,
object
param2
,
object
paramN
,
AsyncCBHandler
asyncDelegate
,
object
asyncContext
);
//必须有参数 AsyncCBHandler asyncDelegate, object asyncContext, 名字不能改。 前面的 param1~paramN, 多少个都行
```
4.
服务中的event, 通过
[
Push(...)
]
可以推送给客户端, 但event 只能是 EventHandler
```
csharp
[
Push
(
typeof
(
BulkDBTempFrameChangedEventArgs
))]
public
event
EventHandler
TempFrameChanged
;
```
WSCF.Test.Client/MainWindow.xaml.cs
View file @
b7320a4a
...
@@ -28,6 +28,9 @@ namespace WSCF.Test.Client
...
@@ -28,6 +28,9 @@ namespace WSCF.Test.Client
{
{
InitializeComponent
();
InitializeComponent
();
//创建连接
//正常情况 FObjServiceClientManager 从配置文件读取
//最终的目标方便 UnityContainer 使用
WSCF
.
FObjServiceClientManager
.
Instance
.
DefaultAddrs
.
Add
(
new
ConnDefaultAddr
()
{
Addr
=
"127.0.0.1:5540"
,
ConnName
=
"foo"
});
WSCF
.
FObjServiceClientManager
.
Instance
.
DefaultAddrs
.
Add
(
new
ConnDefaultAddr
()
{
Addr
=
"127.0.0.1:5540"
,
ConnName
=
"foo"
});
mainVm
=
new
MainVm
();
mainVm
=
new
MainVm
();
...
@@ -56,7 +59,7 @@ namespace WSCF.Test.Client
...
@@ -56,7 +59,7 @@ namespace WSCF.Test.Client
}
}
public
void
Init
()
public
void
Init
()
{
{
//后面的 "foo" 是连接的名字,对应 上面 { Addr = "127.0.0.1:5540", ConnName = "foo" }
Foo
=
new
WSCF
.
Test
.
ServiceClient
.
FooServiceClient
(
"Foo"
,
true
,
"foo"
);
Foo
=
new
WSCF
.
Test
.
ServiceClient
.
FooServiceClient
(
"Foo"
,
true
,
"foo"
);
}
}
void
Add
()
void
Add
()
...
...
WSCF.Test/IService/IFooService.cs
View file @
b7320a4a
...
@@ -7,16 +7,91 @@ using System.Threading.Tasks;
...
@@ -7,16 +7,91 @@ using System.Threading.Tasks;
namespace
WSCF.Test.IService
namespace
WSCF.Test.IService
{
{
/// <summary>
/// 服务接口 继承INotifyPropertyChanged的,PropertyChanged事件 已经在基类实现,不需要显式 Push() 声明
/// </summary>
public
interface
IFooService
:
INotifyPropertyChanged
public
interface
IFooService
:
INotifyPropertyChanged
{
{
string
Msg
{
get
;
set
;
}
int
Number
{
get
;
}
int
Number
{
get
;
}
DateTime
AddFuncTime
{
get
;
}
DateTime
AddFuncTime
{
get
;
}
/// <summary>
/// 只支持 数组, List, ObservableCollection 都不支持
/// </summary>
int
[]
Abc
{
get
;
}
/// <summary>
/// ProfileParam 是 INotifyPropertyChanged, 而且它是单例,
/// 只能通过 PropertyPush 声明, 才能注册 Param.PropertyChanged 事件;
/// 实现 Param 里面的 属性变化,同步到 客户端与服务器
/// 这个 Param 里面不能用 method, 它只是 property 的集合体
/// 当 ProfileParam内还有 property 是 INotifyPropertyChanged 要继续通过 PropertyPush 声明
/// </summary>
[
PropertyPush
]
ProfileParam
Param
{
get
;
}
/// <summary>
/// 只要是event, 只能是 EventHandler类,
/// EventArgs e, 通过 Push() 声明
/// DataChangedEventArgs 必须是 继承 EventArgs
/// </summary>
[
Push
(
typeof
(
DataChangedEventArgs
))]
event
EventHandler
DataChanged
;
/// <summary>
/// 带返回的方法, 只能通过 回调函数的方法返回。 asyncDelegate
/// 返回的数据类型 通过 Call() 声明, 对应 asyncDelegate(asyncContext, retData) 中的 retData
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <param name="asyncDelegate"></param>
/// <param name="asyncContext"></param>
[
Call
(
typeof
(
FooServiceAddReponse
))]
[
Call
(
typeof
(
FooServiceAddReponse
))]
void
Add
(
int
a
,
int
b
,
AsyncCBHandler
asyncDelegate
,
object
asyncContext
);
void
Add
(
int
a
,
int
b
,
AsyncCBHandler
asyncDelegate
,
object
asyncContext
);
/// <summary>
/// 这个方法 不带返回,会自动 添加 Call() , 不需要手动写
/// </summary>
/// <param name="param"></param>
void
Apply
(
ProfileParam
param
);
}
}
public
class
FooServiceAddReponse
public
class
FooServiceAddReponse
{
{
public
int
result
;
public
int
result
;
}
}
public
class
DataChangedEventArgs
:
EventArgs
{
public
DateTime
Time
;
public
string
Msg
;
}
public
class
ProfileParam
:
INotifyPropertyChanged
{
#
region
正常运行参数
/// <summary>
/// 产品名称
/// </summary>
public
string
PName
{
get
;
set
;
}
=
"pname"
;
/// <summary>
/// 目标值
/// </summary>
public
double
Target
{
get
;
set
;
}
=
100
;
#
endregion
/// <summary>
///
/// </summary>
public
event
PropertyChangedEventHandler
PropertyChanged
;
}
}
}
WSCF.Test/Server.WsProxy/WsProxy.cs
View file @
b7320a4a
...
@@ -18,7 +18,7 @@ namespace WSCF.Test.Server.WsProxy
...
@@ -18,7 +18,7 @@ namespace WSCF.Test.Server.WsProxy
{
{
wsproxy
.
Init
(
typeof
(
IFooService
),
foo
);
wsproxy
.
Init
(
typeof
(
IFooService
),
foo
);
});
});
//如果有多个服务,就继续 wssv.AddWebSocketService<Reflect_Proxy>
this
.
wssv
.
Start
();
this
.
wssv
.
Start
();
}
}
}
}
...
...
WSCF.Test/Server/Foo.cs
View file @
b7320a4a
...
@@ -13,8 +13,15 @@ namespace WSCF.Test.Server
...
@@ -13,8 +13,15 @@ namespace WSCF.Test.Server
{
{
public
int
Number
{
get
;
protected
set
;
}
public
int
Number
{
get
;
protected
set
;
}
public
DateTime
AddFuncTime
{
get
;
protected
set
;
}
public
DateTime
AddFuncTime
{
get
;
protected
set
;
}
public
string
Msg
{
get
;
set
;
}
public
int
[]
Abc
{
get
;
protected
set
;
}
public
ProfileParam
Param
{
get
;
}
=
new
ProfileParam
();
public
event
PropertyChangedEventHandler
PropertyChanged
;
public
event
PropertyChangedEventHandler
PropertyChanged
;
public
event
EventHandler
DataChanged
;
public
DispatcherTimer
timer
=
new
DispatcherTimer
();
public
DispatcherTimer
timer
=
new
DispatcherTimer
();
public
Foo
()
public
Foo
()
...
@@ -25,9 +32,27 @@ namespace WSCF.Test.Server
...
@@ -25,9 +32,27 @@ namespace WSCF.Test.Server
timer
.
Start
();
timer
.
Start
();
}
}
int
timecnt
=
0
;
private
void
Timer_Tick
(
object
sender
,
EventArgs
e
)
private
void
Timer_Tick
(
object
sender
,
EventArgs
e
)
{
{
Number
++;
Number
++;
List
<
int
>
abc
=
new
List
<
int
>();
Random
r
=
new
Random
();
for
(
int
i
=
0
;
i
<
3
;
i
++)
{
abc
.
Add
(
r
.
Next
(
10
));
}
Abc
=
abc
.
ToArray
();
timecnt
++;
if
(
timecnt
>
3
)
{
timecnt
=
0
;
DataChanged
?.
Invoke
(
this
,
new
DataChangedEventArgs
()
{
Time
=
DateTime
.
Now
,
Msg
=
"hello "
+
Msg
});
;
}
}
}
public
void
Add
(
int
a
,
int
b
,
AsyncCBHandler
asyncDelegate
,
object
asyncContext
)
public
void
Add
(
int
a
,
int
b
,
AsyncCBHandler
asyncDelegate
,
object
asyncContext
)
...
@@ -36,5 +61,11 @@ namespace WSCF.Test.Server
...
@@ -36,5 +61,11 @@ namespace WSCF.Test.Server
AddFuncTime
=
DateTime
.
Now
;
AddFuncTime
=
DateTime
.
Now
;
asyncDelegate
?.
Invoke
(
asyncContext
,
new
FooServiceAddReponse
()
{
result
=
Number
});
asyncDelegate
?.
Invoke
(
asyncContext
,
new
FooServiceAddReponse
()
{
result
=
Number
});
}
}
public
void
Apply
(
ProfileParam
param
)
{
Param
.
PName
=
param
.
PName
;
Param
.
Target
=
param
.
Target
;
}
}
}
}
}
WSCF.Test/ServiceClient/FooServiceClient.cs
View file @
b7320a4a
...
@@ -7,23 +7,50 @@ using WSCF.Test.IService;
...
@@ -7,23 +7,50 @@ using WSCF.Test.IService;
namespace
WSCF.Test.ServiceClient
namespace
WSCF.Test.ServiceClient
{
{
//很机械式 按格式填就好,下一个版本,会有软件 自动生成下面的代码
public
class
FooServiceClient
:
Reflect_SeviceClient
,
IFooService
public
class
FooServiceClient
:
Reflect_SeviceClient
,
IFooService
{
{
//注明要实现的服务接口
protected
override
Type
InterfaceType
=>
typeof
(
IFooService
);
protected
override
Type
InterfaceType
=>
typeof
(
IFooService
);
//只要是property,get, set 都必须 public 就算 IFooService.Number 只有 Get没有Set
public
int
Number
{
get
;
set
;
}
public
int
Number
{
get
;
set
;
}
public
DateTime
AddFuncTime
{
get
;
set
;
}
public
DateTime
AddFuncTime
{
get
;
set
;
}
public
string
Msg
{
get
;
set
;
}
public
int
[]
Abc
{
get
;
set
;
}
public
ProfileParam
Param
{
get
;
}
=
new
ProfileParam
();
public
FooServiceClient
(
string
serverName
,
bool
isByConnName
,
string
addrOrConnName
):
base
(
serverName
,
isByConnName
,
addrOrConnName
)
public
FooServiceClient
(
string
serverName
,
bool
isByConnName
,
string
addrOrConnName
):
base
(
serverName
,
isByConnName
,
addrOrConnName
)
{
{
}
}
public
event
EventHandler
DataChanged
;
/// <summary>
/// 只要是事件,都只能手动 创建 Trigger_xxxx(xxxx为event名称),作为触发事件的函数,该函数的参数类型就是Push 里面定义的
/// </summary>
/// <param name="e"></param>
public
void
Trigger_DataChanged
(
DataChangedEventArgs
e
)
{
DataChanged
?.
Invoke
(
this
,
e
);
}
public
void
Add
(
int
a
,
int
b
,
AsyncCBHandler
asyncDelegate
,
object
asyncContext
)
public
void
Add
(
int
a
,
int
b
,
AsyncCBHandler
asyncDelegate
,
object
asyncContext
)
{
{
//Call 的 parameters 必须写 为 new {a, b} 这样简写模式, 因为需要匹配 参数名字
Call
(
nameof
(
Add
),
new
{
a
,
b
},
asyncDelegate
,
asyncContext
);
Call
(
nameof
(
Add
),
new
{
a
,
b
},
asyncDelegate
,
asyncContext
);
}
}
public
void
Apply
(
ProfileParam
param
)
{
//如果连参数也没有,只需要写 Call(nameof(Apply));
Call
(
nameof
(
Apply
),
new
{
param
});
}
}
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment