Commit 936c9ebe authored by 潘栩锋's avatar 潘栩锋 🚴
parents b7320a4a 64a8f5dc
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using WebSocketSharp.Server; using WebSocketSharp.Server;
using WSCF.Test.IService; using WSCF.Test.IService;
...@@ -16,7 +17,14 @@ namespace WSCF.Test.Server.WsProxy ...@@ -16,7 +17,14 @@ namespace WSCF.Test.Server.WsProxy
wssv = new WebSocketServer($"ws://{addr}/"); wssv = new WebSocketServer($"ws://{addr}/");
wssv.AddWebSocketService<Reflect_Proxy>("/Foo", (wsproxy) => wssv.AddWebSocketService<Reflect_Proxy>("/Foo", (wsproxy) =>
{ {
wsproxy.Init(typeof(IFooService), foo); //wsproxy.Init(typeof(IFooService), foo);
wsproxy.AfterOpen = (proxy) =>
{
//分解 路径
string path = proxy.Context.RequestUri.PathAndQuery;
proxy.Init(typeof(IFooService), foo);
};
}); });
//如果有多个服务,就继续 wssv.AddWebSocketService<Reflect_Proxy> //如果有多个服务,就继续 wssv.AddWebSocketService<Reflect_Proxy>
this.wssv.Start(); this.wssv.Start();
......
...@@ -11,6 +11,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WSCF.Test", "WSCF.Test\WSCF ...@@ -11,6 +11,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WSCF.Test", "WSCF.Test\WSCF
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WSCF.Test.Client", "WSCF.Test.Client\WSCF.Test.Client.csproj", "{FEBF0580-906C-497D-9184-58055B305DF9}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WSCF.Test.Client", "WSCF.Test.Client\WSCF.Test.Client.csproj", "{FEBF0580-906C-497D-9184-58055B305DF9}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WSCF.standard", "WSCF.standard\WSCF.standard.csproj", "{1565CFC6-79B7-4D91-9B07-1C03C2E1929F}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
...@@ -33,6 +35,10 @@ Global ...@@ -33,6 +35,10 @@ Global
{FEBF0580-906C-497D-9184-58055B305DF9}.Debug|Any CPU.Build.0 = Debug|Any CPU {FEBF0580-906C-497D-9184-58055B305DF9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FEBF0580-906C-497D-9184-58055B305DF9}.Release|Any CPU.ActiveCfg = Release|Any CPU {FEBF0580-906C-497D-9184-58055B305DF9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FEBF0580-906C-497D-9184-58055B305DF9}.Release|Any CPU.Build.0 = Release|Any CPU {FEBF0580-906C-497D-9184-58055B305DF9}.Release|Any CPU.Build.0 = Release|Any CPU
{1565CFC6-79B7-4D91-9B07-1C03C2E1929F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1565CFC6-79B7-4D91-9B07-1C03C2E1929F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1565CFC6-79B7-4D91-9B07-1C03C2E1929F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1565CFC6-79B7-4D91-9B07-1C03C2E1929F}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
......
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<PropertyChanged />
</Weavers>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="PropertyChanged" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="InjectOnPropertyNameChanged" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to control if the On_PropertyName_Changed feature is enabled.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="TriggerDependentProperties" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to control if the Dependent properties feature is enabled.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="EnableIsChangedProperty" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to control if the IsChanged property feature is enabled.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="EventInvokerNames" type="xs:string">
<xs:annotation>
<xs:documentation>Used to change the name of the method that fires the notify event. This is a string that accepts multiple values in a comma separated form.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="CheckForEquality" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to control if equality checks should be inserted. If false, equality checking will be disabled for the project.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="CheckForEqualityUsingBaseEquals" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to control if equality checks should use the Equals method resolved from the base class.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="UseStaticEqualsFromBase" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to control if equality checks should use the static Equals method resolved from the base class.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="SuppressWarnings" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to turn off build warnings from this weaver.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="SuppressOnPropertyNameChangedWarning" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to turn off build warnings about mismatched On_PropertyName_Changed methods.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>
\ No newline at end of file
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace>WSCF</RootNamespace>
<Authors>panruising</Authors>
<Company>flyautomation</Company>
<Description>WSCF (WebSocket Communication Foundation) 就是 抄 微软的WCF, 但有 推送功能。</Description>
<PackageProjectUrl>http://private.flyautomation.net:82/panruising/wscf</PackageProjectUrl>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
<Version>1.0.2</Version>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DefineConstants>TRACE;NETSTANDARD</DefineConstants>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\WSCF\AsyncCBHandler.cs" Link="AsyncCBHandler.cs" />
<Compile Include="..\WSCF\CallAttribute.cs" Link="CallAttribute.cs" />
<Compile Include="..\WSCF\FObjServiceClientManager.cs" Link="FObjServiceClientManager.cs" />
<Compile Include="..\WSCF\ReflectData.cs" Link="ReflectData.cs" />
<Compile Include="..\WSCF\Reflect_Proxy.cs" Link="Reflect_Proxy.cs" />
<Compile Include="..\WSCF\Reflect_SeviceClient.cs" Link="Reflect_SeviceClient.cs" />
<Compile Include="..\WSCF\WebSocketClient.cs" Link="WebSocketClient.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="NLog" Version="4.6.8" />
<PackageReference Include="PropertyChanged.Fody" Version="3.3.1" />
<PackageReference Include="WebSocketSharp-netstandard" Version="1.0.1" />
</ItemGroup>
</Project>
...@@ -38,6 +38,7 @@ namespace WSCF ...@@ -38,6 +38,7 @@ namespace WSCF
this.interfaceType = interfaceType; this.interfaceType = interfaceType;
this.obj = obj; this.obj = obj;
//注册 obj 的PropertyChanged 事件,获取 interfaceType 全部属性名称,包括它的父类的全部属性名称
InitPropertyChanged(); InitPropertyChanged();
//处理[PropertyPush] //处理[PropertyPush]
...@@ -76,15 +77,7 @@ namespace WSCF ...@@ -76,15 +77,7 @@ namespace WSCF
}, this.obj)); }, this.obj));
var interfaceTypes = new List<Type>(); var propertyInfos = GetAllPropertyInfos();//获取全部属性, 包括父类的属性
interfaceTypes.Add(this.interfaceType);
interfaceTypes.AddRange(this.interfaceType.GetInterfaces());
var propertyInfos = new List<PropertyInfo>();
foreach (var ifaceType in interfaceTypes)
{
propertyInfos.AddRange(ifaceType.GetProperties());
}
foreach (var propertyInfo in propertyInfos) foreach (var propertyInfo in propertyInfos)
{ {
...@@ -97,6 +90,23 @@ namespace WSCF ...@@ -97,6 +90,23 @@ namespace WSCF
properties.Add(propertyInfo.Name); properties.Add(propertyInfo.Name);
} }
} }
/// <summary>
/// 获取全部属性, 包括父类的属性
/// </summary>
/// <returns></returns>
List<PropertyInfo> GetAllPropertyInfos()
{
var interfaceTypes = new List<Type>();
interfaceTypes.Add(this.interfaceType);
interfaceTypes.AddRange(this.interfaceType.GetInterfaces());
var propertyInfos = new List<PropertyInfo>();//获取全部属性, 包括父类的属性
foreach (var ifaceType in interfaceTypes)
{
propertyInfos.AddRange(ifaceType.GetProperties());
}
return propertyInfos;
}
void InitEventPush() void InitEventPush()
{ {
var interfaceTypes = new List<Type>(); var interfaceTypes = new List<Type>();
...@@ -145,14 +155,7 @@ namespace WSCF ...@@ -145,14 +155,7 @@ namespace WSCF
void InitPropertyPush() void InitPropertyPush()
{ {
//处理[PropertyPush] //处理[PropertyPush]
var interfaceTypes = new List<Type>(); var propertyInfos = GetAllPropertyInfos();//获取全部属性, 包括父类的属性
interfaceTypes.Add(this.interfaceType);
interfaceTypes.AddRange(this.interfaceType.GetInterfaces());
var propertyInfos = new List<PropertyInfo>();
foreach (var ifaceType in interfaceTypes)
propertyInfos.AddRange(ifaceType.GetProperties());
foreach (var propertyInfo in propertyInfos) foreach (var propertyInfo in propertyInfos)
...@@ -165,6 +168,9 @@ namespace WSCF ...@@ -165,6 +168,9 @@ namespace WSCF
properties.Add(propertyInfo.Name); properties.Add(propertyInfo.Name);
} }
//这个属性可能是 父类的, interfaceType可能没有;
//obj 肯定有
//继续枚举 propertyInfo 下面的 [PropertyPush]
InitSubPropertyPush(this.obj.GetType().GetProperty(propertyInfo.Name), this.obj, null); InitSubPropertyPush(this.obj.GetType().GetProperty(propertyInfo.Name), this.obj, null);
} }
} }
...@@ -208,8 +214,8 @@ namespace WSCF ...@@ -208,8 +214,8 @@ namespace WSCF
} }
private void Obj_PropertyChanged(object sender, PropertyChangedEventArgs e) private void Obj_PropertyChanged(object sender, PropertyChangedEventArgs e)
{ {
if (ignoreSet)//从服务器接收的数据,不用再推送给服务器 //if (ignoreSet)//从服务器接收的数据,不用再推送给服务器
return; // return;
if (interfaceType == null) if (interfaceType == null)
return; return;
...@@ -245,8 +251,8 @@ namespace WSCF ...@@ -245,8 +251,8 @@ namespace WSCF
} }
private void Sub_PropertyChanged(object sender, PropertyChangedEventArgs e) private void Sub_PropertyChanged(object sender, PropertyChangedEventArgs e)
{ {
if (ignoreSet)//从服务器接收的数据,不用再推送给服务器 //if (ignoreSet)//从服务器接收的数据,不用再推送给服务器
return; // return;
if (!subProperties.ContainsKey(sender)) if (!subProperties.ContainsKey(sender))
return;//异常, 不是子property return;//异常, 不是子property
...@@ -295,8 +301,11 @@ namespace WSCF ...@@ -295,8 +301,11 @@ namespace WSCF
{ {
base.OnOpen(); base.OnOpen();
isAlive = true; isAlive = true;
AfterOpen?.Invoke(this);
} }
public Action<Reflect_Proxy> AfterOpen;
protected override void OnClose(CloseEventArgs e) protected override void OnClose(CloseEventArgs e)
{ {
base.OnClose(e); base.OnClose(e);
...@@ -343,19 +352,26 @@ namespace WSCF ...@@ -343,19 +352,26 @@ namespace WSCF
break; break;
case Reflect_OBJ_INTERFACE.PkgName.CALL_SetProperty: case Reflect_OBJ_INTERFACE.PkgName.CALL_SetProperty:
{ {
ignoreSet = true; //ignoreSet = true;
//TODO //TODO
string json = pkgData.data.ToString(); string json = pkgData.data.ToString();
JsonConvert.PopulateObject(json, obj); JsonConvert.PopulateObject(json, obj);
ignoreSet = false; //ignoreSet = false;
} }
break; break;
case Reflect_OBJ_INTERFACE.PkgName.CALL_MethodInvoke: case Reflect_OBJ_INTERFACE.PkgName.CALL_MethodInvoke:
{ {
var rData = pkgData.data.ToObject<Reflect_OBJ_INTERFACE.ReflectData>(); var rData = pkgData.data.ToObject<Reflect_OBJ_INTERFACE.ReflectData>();
var type = obj.GetType(); var type = obj.GetType();
var methodInfo = type.GetMethod(rData.name); var paramNames_req = rData.data.Children().OfType<JProperty>().Select(p => p.Name);
MethodInfo methodInfo = GetMethodInfo(type, rData.name, paramNames_req);
if (methodInfo == null)
{
//不能找到,
throw new Exception($"程序写错了, 不能找到 rData.name={rData.name} 或者 参数名称不对,没法完全匹配");
}
var parameterInfos = methodInfo.GetParameters(); var parameterInfos = methodInfo.GetParameters();
object[] parameters = new object[parameterInfos.Count()]; object[] parameters = new object[parameterInfos.Count()];
for (int i = 0; i < parameters.Count(); i++) for (int i = 0; i < parameters.Count(); i++)
...@@ -381,7 +397,41 @@ namespace WSCF ...@@ -381,7 +397,41 @@ namespace WSCF
} }
MethodInfo GetMethodInfo(Type type, string name, IEnumerable<string> parameterNames)
{
var methodInfos = from mi in type.GetMethods() where mi.Name == name select mi;
if (methodInfos.Count() == 0)
return null;
if (methodInfos.Count() == 1)
return methodInfos.First();
//必须完全匹配
foreach (var methodInfo in methodInfos)
{
var parameterInfos = methodInfo.GetParameters();
//全部参数名称
var names = parameterInfos.Select(pi => pi.Name).ToList();
//删除掉 asyncDelegate,asyncContext
names.Remove(Reflect_OBJ_INTERFACE.asyncDelegate);
names.Remove(Reflect_OBJ_INTERFACE.asyncContext);
var names_req = parameterNames;
if (names.Count() != names_req.Count())
continue;//数量不一致,肯定不同
var sames = names_req.Intersect(names);
if (sames.Count() != names_req.Count())
continue;// names 与 names_req 的交集数量与names_req不一样,肯定不同
//就是它
return methodInfo;
}
return null;
}
void asyncDelegate(object asyncContext, object retData) void asyncDelegate(object asyncContext, object retData)
{ {
var cc = (CC)asyncContext; var cc = (CC)asyncContext;
......
...@@ -348,6 +348,10 @@ namespace WSCF ...@@ -348,6 +348,10 @@ namespace WSCF
//触发事件!!! //触发事件!!!
var methodInfo = GetType().GetMethod(anyEvent.triggerName); var methodInfo = GetType().GetMethod(anyEvent.triggerName);
if (methodInfo == null)
{
throw new Exception($"客户端 {GetType()} 忘记写 {anyEvent.triggerName}");
}
var obj = rData.data.ToObject(anyEvent.retType); var obj = rData.data.ToObject(anyEvent.retType);
//出错,就提示,肯定是客户端忘记写 "Trigger_XXXX" //出错,就提示,肯定是客户端忘记写 "Trigger_XXXX"
methodInfo.Invoke(this, new object[] { obj }); methodInfo.Invoke(this, new object[] { obj });
......
oy2l7ego5jz6t2hsieaqbuw5xulxyrseznzgl3vhsab7pm
\ No newline at end of file
dotnet nuget push WSCF.standard/bin/Debug/WSCF.standard.1.0.2.nupkg --api-key oy2l7ego5jz6t2hsieaqbuw5xulxyrseznzgl3vhsab7pm --source https://api.nuget.org/v3/index.json
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment