2309d自定义属性

阅读: 评论:0

2309d自定义属性

2309d自定义属性

原文
如果想要更强大示例,下面是使用UDA来轻松定义无缝回复是否成功回调的调用函数RPC模块的概念证明.

questName().onSuccess((string str) {writefln("We got the name reply back from the server: %s", str);
}).onFailure((string errMsg) {writefln("Something went wrong! Error: %s", errMsg);
});

此例省略了系统的实际网络部分,而只是在目标对象上直接调用函数,并立即回复.在真实世界示例中,会序化函数请求及其参数,及指定要调用对象唯一标识,通过网络或线程传递,并在目标进程上解码并运行,然后同样序化返回回复.

可按调用者等待直到收到回复或失败同步,或定期处理回调的异步来调整系统.如,假设把简单的.async插入调用链,并指定超时其他选项.

除此外,该程序应完全编译并说明系统如何工作.

import std.stdio;
import std.format;
aits;
ption;
atraits;
class Person {mixin ProxyReceiver;string name;int age;this(string name, int age) {this.name = name;this.age = age;}@Proxy@Reply!(string)void requestName() {writefln("SERVER# User requested name");reply(name);}@Proxy@Reply!(bool)void setName(string s) {writefln("SERVER# Changed name to: %s", s);this.name = s;reply(true);}@Proxy@Reply!(int)@Failure!(string)void doubleEvenNumber(int x) {writefln("SERVER# User wants to double number: %s", x);if (!(x % 2)) reply(x * 2, x);else failure("Supplied number is not even.");}
}
struct ) {}
struct ) {}
mixin template ProxyReceiver() {Proxy!(typeof(this)) _proxy;void reply(string funcstr = __FUNCTION__, RA...)(RA rargs) {_ply!(funcstr)(rargs);}void failure(string funcstr = __FUNCTION__, RA...)(RA rargs) {_proxy.failure!(funcstr)(rargs);}
}
class Proxy(Destination) {Destination dest;private static abstract class Callback {MsgNum msgNum;double startTime, timeout;}private static final class CallbackT(alias FUNC) : Callback {static if (hasUDA!(FUNC, Reply)) {alias SUCCESS = void delegate(TemplateArgsOf!(getUDAs!(FUNC, Reply)[0]));SUCCESS successDG;}static if (hasUDA!(FUNC, Failure)) {alias FAILURE = void delegate(TemplateArgsOf!(getUDAs!(FUNC, Failure)[0]));FAILURE failureDG;}}alias MsgNum = uint;MsgNum nextMsgNum = 1;Callback[MsgNum] callbacks;MsgNum lastMessageNum;alias FIRE = void delegate();FIRE[MsgNum] pendingCalls; //在此处使用闭包来模拟`网络延迟`,以留出时间添加回调this(Destination dest) {this.dest = dest;dest._proxy = this;}void reply(string funcstr = __FUNCTION__, RA...)(RA rargs) {mixin(`alias FUNC = `~funcstr~`;`);alias FQN = fullyQualifiedName!FUNC;static assert(hasUDA!(FUNC, Reply), "No reply allowed for func: "~FQN);alias UDA = getUDAs!(FUNC, Reply)[0];alias RFUNC = void delegate(TemplateArgsOf!UDA);static assert(canCallFuncWithParameters!(RFUNC, RA), format("Invalid parameters for reply: %s (expected %s)", RA.stringof, Parameters!RFUNC.stringof));auto msgNum = lastMessageNum;auto p = msgNum in callbacks;enforce(p, format("Callback not found: #%s", msgNum));auto cbase = *ve(msgNum);auto cb = cast(CallbackT!FUNC) cbase;enforce(cb, "Callback mismatch: could not cast to %s", CallbackT!FUNC.stringof);//writefln("准备用参数:%s调用cb(%s)闭包",rargs,cb);if (cb.successDG !is null) {cb.successDG(rargs);cb.successDG = null;}}void failure(string funcstr = __FUNCTION__, RA...)(RA rargs) {mixin(`alias FUNC = `~funcstr~`;`);alias FQN = fullyQualifiedName!FUNC;static assert(hasUDA!(FUNC, Failure), "No failure allowed for func: "~FQN);alias UDA = getUDAs!(FUNC, Failure)[0];alias RFUNC = void delegate(TemplateArgsOf!UDA);static assert(canCallFuncWithParameters!(RFUNC, RA), format("Invalid parameters for failure: %s (expected %s)", RA.stringof, Parameters!RFUNC.stringof));auto msgNum = lastMessageNum;auto p = msgNum in callbacks;enforce(p, format("Callback not found: #%s", msgNum));auto cbase = *ve(msgNum);auto cb = cast(CallbackT!FUNC) cbase;enforce(cb, "Callback mismatch: could not cast to %s", CallbackT!FUNC.stringof);if (cb.failureDG !is null) {cb.failureDG(rargs);cb.failureDG = null;}}struct Outbound(alias FUNC) {this() @disable;this(this) @disable;~this() {//writefln("~Outbound!%s [%s:%s]", FUNCNAME!FUNC, msgNum, fired);if (!fired)go();}alias FQN = fullyQualifiedName!FUNC;static if (hasUDA!(FUNC, Reply)) {alias SUCCESS = void delegate(TemplateArgsOf!(getUDAs!(FUNC, Reply)[0]));}static if (hasUDA!(FUNC, Failure)) {alias FAILURE = void delegate(TemplateArgsOf!(getUDAs!(FUNC, Failure)[0]));}private Proxy proxy;private MsgNum msgNum;private bool fired;private this(Proxy proxy, MsgNum n) {this.proxy = proxy;this.msgNum = n;}static if (is(SUCCESS))auto onSuccess(SUCCESS dg) scope return {static assert(is(SUCCESS), ("Reply not allowed for %s", FQN));CallbackT!FUNC cb;if (auto p = msgNum in proxy.callbacks) {cb = cast(CallbackT!FUNC) *p;assert(cb, "Callback type mismatch");assert(cb.successDG is null, "Success callback already set");} else {cb = new CallbackT!FUNC;cb.msgNum = msgNum;proxy.callbacks[cb.msgNum] = cb;}cb.successDG = dg;fired = true; //返回新结构,因此现已失效return Outbound(proxy, msgNum);}static if (is(FAILURE))auto onFailure(FAILURE dg) scope return {static assert(is(FAILURE), ("Failure not allowed for %s", FQN));CallbackT!FUNC cb;if (auto p = msgNum in proxy.callbacks) {cb = cast(CallbackT!FUNC) *p;assert(cb, "Callback type mismatch");assert(cb.failureDG is null, "Failure callback already set");} else {cb = new CallbackT!FUNC;cb.msgNum = msgNum;proxy.callbacks[cb.msgNum] = cb;}cb.failureDG = dg;fired = true; //返回新结构,因此现已失效return Outbound(proxy, msgNum);}void go() {if (fired) return;fired = true;if (auto fireDG = msgNum in proxy.pendingCalls) {ve(msgNum);(*fireDG)();}}}auto opDispatch(string s, SA...)(SA sargs) {//writefln("opDispatch:<%s>%s",s,SA.stringof);alias FUNC = __traits(getMember, dest, s);alias FN = FUNCNAME!FUNC;alias FQN = fullyQualifiedName!FUNC;static if (!hasTemplateUDA!(FUNC, Proxy)) {pragma(msg, format("Cannot call function %s without @Proxy UDA", FQN)); //在`opDispatch`中难以取编译错误消息static assert(false);}alias PARAMS = Parameters!FUNC;static if (!canCallFuncWithParameters!(FUNC, SA)) {pragma(msg, format("Invalid parameters for proxy %s: expected %s, got %s", FQN, PARAMS.stringof, SA.stringof));static assert(false, "Invalid parameters");} else {auto msgNum = nextMsgNum++;auto outbound = Outbound!FUNC(this, msgNum);pendingCalls[msgNum] = {//此闭包直接调用接收方对象.实际上,按发射器/接收器对拆分代理,并跨要重构`网络`序化消息,并在`目标对象`上远程调用接收器.lastMessageNum = msgNum;__traits(getMember, dest, s)(sargs);};return outbound;}}
}
void main() {auto person = new Person("bob", 34);auto proxy = new Proxy!Person(person);questName().onSuccess((string str) {writefln("Client| Received name: %s", str);});proxy.doubleEvenNumber(4).onSuccess((int r, int orig) {writefln("Client| Received doubled number: %s (Original number was: %s)", r, orig);}).onFailure((string str) {writefln("Client| Error: %s", str);});proxy.doubleEvenNumber(3).onSuccess((int r, int orig) {writefln("Client| Received doubled number: %s (Original number was: %s)", r, orig);}).onFailure((string str) {writefln("Client| Error: %s", str);});assert(proxy.callbacks.length == 0, format("Unhandled callbacks: %s", proxy.callbacks));
}
.
My util/extratraits.d for some additional helper templates:
atraits;
aits;
template ) if (F.length == 1) {import std.string;enum FUNCNAME = fullyQualifiedName!(F[0])[ fullyQualifiedName!(F[0]).lastIndexOf('.')+1 .. $ ];
}
bool canCallFuncWithParameters(alias FUNC, SA...)() pure @safe nothrow {static if (SA.length > Parameters!FUNC.length || SA.length < numRequiredArguments!FUNC) {return false;}static foreach (idx, P; Parameters!FUNC) {static if (idx < SA.length && !isImplicitlyConvertible!(SA[idx], P)) {return false;}}return true;
}
size_t numRequiredArguments(alias FUNC)() pure @safe nothrow {size_t numReq = 0;static foreach (argi, PD; ParameterDefaults!FUNC) {static if (is(PD == void))numReq++;elsereturn numReq;}return numReq;
}
string shortname()(string str) {import std.string;auto excl = str.indexOf('!');if (excl > 0) str = str[0 .. excl];return str[str.lastIndexOf('.')+1 .. $];
}
bool hasTemplateUDA(alias SYM, alias UDA)() {static foreach (idx, attr; __traits(getAttributes, SYM)) {static if (__traits(isTemplate, TemplateOf!UDA)) {static if (__traits(isSame, attr, TemplateOf!UDA))return true;} else {static if (__traits(isSame, attr, UDA))return true;}}return false;
}
template isMemberVariable(alias THIS, alias SYM) if (isAggregateType!THIS) {enum bool isMemberVariable = !(isFunction!SYM || isType!SYM || __traits(isTemplate, SYM)//|| hasStaticMember!(THIS, SYM.stringof));
}

本文发布于:2024-02-02 17:47:51,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170686727245424.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:自定义   属性
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23