提高代码重用(c#?)的Python风格装饰器)
我正在从python迁移到c#,我错过的一件事是python风格的装饰器。如果我在一堆函数的顶部重复代码(验证检查等),我可以创建一个装饰器来完成这项工作 我已经看到有某种c#decorator,但它们看起来更像是在类级别上工作。虽然我被他们弄糊涂了 不管怎样-您将如何改进此函数中的代码重用/干燥?函数中的所有内容都是通用的,除了标记的两个位置。它对服务器的回调驱动的Tcp请求,带有一个阻止多个并发请求的块(检查空闲状态)提高代码重用(c#?)的Python风格装饰器),c#,python,dry,C#,Python,Dry,我正在从python迁移到c#,我错过的一件事是python风格的装饰器。如果我在一堆函数的顶部重复代码(验证检查等),我可以创建一个装饰器来完成这项工作 我已经看到有某种c#decorator,但它们看起来更像是在类级别上工作。虽然我被他们弄糊涂了 不管怎样-您将如何改进此函数中的代码重用/干燥?函数中的所有内容都是通用的,除了标记的两个位置。它对服务器的回调驱动的Tcp请求,带有一个阻止多个并发请求的块(检查空闲状态) public void MyFunction(字符串、操作onSucce
public void MyFunction(字符串、操作onSuccess=null、操作onError=null)
{
//如果已忙于操作,则引发异常
如果(!state.Has(state.Idle)){抛出新操作进程();}
//定义回调操作
动作回调=委托(TcpRequest请求)
{
//将空闲状态添加回
state.Add(state.Idle);
//检查请求是否成功
if(request.OK)
{
/**
*这里的唯一代码
*/
}
//请求失败。如果提供,请调用OneError回调
else{onError?.Invoke(request);}
};
//清除空闲状态
state.Remove(state.Idle);
/**
*此处的唯一代码,稍后将触发回调
*/
}
编辑:我不是真的认为这是一个代码审查任务,但现在我可以看到它是。下面是整个类,展示了状态/变量如何交互。Server类处理我们(客户端)和Web服务器之间的交互,以处理游戏登录和创建/加入匹配
我并不固定在任何特定的结构上,但在某些情况下,我希望将UI按钮连接到简单的函数,如Server.Login()
和Server.JoinMatch()
,而不需要生成混乱的类
public class Server
{
#region Fields
public string playerName { get; private set; }
public string playerID { get; private set; }
public string playerToken { get; private set; }
public string currentMatchID { get; private set; }
private Patterns.State<ServerState> state = new Patterns.State<ServerState>();
#endregion
public Server()
{
state.Add(ServerState.Idle);
}
public void Login(string playerName, Action<TcpRequest> onSuccess = null, Action<TcpRequest> onError = null)
{
// Throw exception already busy with an operation
if (!state.Has(ServerState.Idle)) { throw new OperationInProgress(); }
// Define login callback action
Action<TcpRequest> loginCallback = delegate (TcpRequest request)
{
// Add idle state back in
state.Add(ServerState.Idle);
// Check if the request succeeded
if (request.OK)
{
// Store player data in class
playerName = (string)request.requestJson["player_name"];
playerID = (string)request.responseJson["player_id"];
playerToken = (string)request.responseJson["player_token"];
// Add the logged in state
state.Add(ServerState.LoggedIn);
// Call the onSuccess callback if provided
onSuccess?.Invoke(request);
}
// Login failed, call the onError callback if provided
else { onError?.Invoke(request); }
};
// Remove idle state
state.Remove(ServerState.Idle);
// Perform request
Request("login", callback: loginCallback, requestJson: new Dictionary<string, object> { { "player_name", playerName }, { "client_version", "test1" } });
}
public void CreateMatch(string matchName, Action<TcpRequest> onSuccess = null, Action<TcpRequest> onError = null)
{
// Throw exception already busy with an operation
if (!state.Has(ServerState.Idle)) { throw new OperationInProgress(); }
// Define callback action
Action<TcpRequest> callback = delegate (TcpRequest request)
{
// Add idle state back in
state.Add(ServerState.Idle);
// Check if the request succeeded
if (request.OK)
{
// Add the inLobby state
state.Add(ServerState.InLobby);
// Call the onSuccess callback if provided
onSuccess?.Invoke(request);
}
// Request failed. Call the onError callback if provided
else { onError?.Invoke(request); }
};
// Remove idle state
state.Remove(ServerState.Idle);
// Perform request
AuthenticatedRequest("match/create", callback: callback, requestJson: new Dictionary<string, object> { { "match_name", matchName } });
}
public void JoinMatch(string matchID, Action<TcpRequest> onSuccess = null, Action<TcpRequest> onError = null)
{
// Throw exception already busy with an operation
if (!state.Has(ServerState.Idle)) { throw new OperationInProgress(); }
// Define callback action
Action<TcpRequest> callback = delegate (TcpRequest request)
{
// Add idle state back in
state.Add(ServerState.Idle);
// Check if the request succeeded
if (request.OK)
{
// Add the inLobby state
state.Add(ServerState.InLobby);
// Set currentMatchID in class
currentMatchID = (string)request.responseJson["match_id"];
// Call the onSuccess callback if provided
onSuccess?.Invoke(request);
}
// Request failed. Call the onError callback if provided
else { onError?.Invoke(request); }
};
// Perform request
AuthenticatedRequest("match/join", callback: callback, requestJson: new Dictionary<string, object> { { "match_id", matchID } });
}
private void Request(string resource, Action<TcpRequest> callback = null, Dictionary<string, object> requestJson = null)
{
// Start async request, invoke callback when done
}
private void AuthenticatedRequest(string resource, Action<TcpRequest> callback = null, Dictionary<string, object> requestJson = null)
{
// Add login auth data into the requestJson dict or throw exception if we aren't logged in
// Call Request()
}
}
公共类服务器
{
#区域字段
公共字符串播放器名称{get;private set;}
公共字符串播放器ID{get;private set;}
公共字符串播放器主题{get;private set;}
公共字符串currentMatchID{get;private set;}
private Patterns.State=new Patterns.State();
#端区
公共服务器()
{
state.Add(ServerState.Idle);
}
public void登录(字符串playerName,Action onSuccess=null,Action onError=null)
{
//抛出异常已忙于某个操作
如果(!state.Has(ServerState.Idle)){抛出新操作进程();}
//定义登录回调操作
Action loginCallback=委托(TcpRequest请求)
{
//将空闲状态添加回
state.Add(ServerState.Idle);
//检查请求是否成功
if(request.OK)
{
//在类中存储播放器数据
playerName=(string)request.requestJson[“player_name”];
playerID=(字符串)request.responseJson[“player_id”];
playerToken=(字符串)request.responseJson[“玩家令牌”];
//添加登录状态
state.Add(ServerState.LoggedIn);
//调用onSuccess回调(如果提供)
onSuccess?.Invoke(请求);
}
//登录失败,请调用OneError回调(如果提供)
else{onError?.Invoke(request);}
};
//清除空闲状态
state.Remove(ServerState.Idle);
//执行请求
请求(“login”,回调:loginCallback,requestJson:newdictionary{{“player\u name”,playerName},{“client\u version”,“test1”});
}
public void CreateMatch(字符串匹配名,操作onSuccess=null,操作onError=null)
{
//抛出异常已忙于某个操作
如果(!state.Has(ServerState.Idle)){抛出新操作进程();}
//定义回调操作
动作回调=委托(TcpRequest请求)
{
//将空闲状态添加回
state.Add(ServerState.Idle);
//检查请求是否成功
if(request.OK)
{
//添加inLobby状态
state.Add(ServerState.InLobby);
//调用onSuccess回调(如果提供)
onSuccess?.Invoke(请求);
}
//请求失败。如果提供,请调用OneError回调
else{onError?.Invoke(request);}
};
//清除空闲状态
state.Remove(ServerState.Idle);
//执行请求
AuthenticatedRequest(“匹配/创建”,回调:回调,requestJson:new Dictionary{{{“match_name”,matchName}});
}
public void JoinMatch(字符串matchID,Action onSuccess=null,Action onError=null)
{
//抛出异常已忙于某个操作
如果(!state.Has(ServerState.Idle)){抛出新操作进程();}
//定义回调操作
动作回调=委托(TcpRequest请求)
{
//将空闲状态添加回
state.Add(ServerState.Idle);
//检查请求是否成功
if(request.OK)
{
//添加inLobby状态
state.Add(ServerState.InLobby);
//在类中设置currentMatchID
currentMatchID=(字符串)请求.responseJson[“匹配id”];
//调用onSuccess回调(如果提供)
onSuccess?.Invoke(请求);
}
//请求失败。如果提供,请调用OneError回调
else{onError?.Invoke(request);}
};
//执行请求
AuthenticatedRequest(“match/join”,callback:callback,requestJson:newdictionary{{“match_id”,matchID}});
public abstract class MyClass
{
public void MyFunction(string apples, Action<TcpRequest> onSuccess=null, Action<TcpRequest> onError=null)
{
// Throw exception if already busy with an operation
if (!state.Has(State.Idle)) { throw new OperationInProgress(); }
// Define callback action
Action<TcpRequest> callback = delegate (TcpRequest request)
{
// Add idle state back in
state.Add(State.Idle);
// Check if the request succeeded
if (request.OK)
{
SomethingUnique1();
}
// Request failed. Call the onError callback if provided
else { onError?.Invoke(request); }
};
// Remove idle state
state.Remove(State.Idle);
SomethingUnique2(callback);
}
protected abstract void SomethingUnique1();
protected abstract void SomethingUnique2(Action<TcpRequest> callback);
}
public sealed class MyClassVariant1 : MyClass
{
protected override SomethingUnique1() { /*...*/ }
protected override SomethingUnique2(Action<TcpRequest> callback) { /*...*/ }
}
public sealed class MyClassVariant2 : MyClass
{
protected override SomethingUnique1() { /*...*/ }
protected override SomethingUnique2(Action<TcpRequest> callback) { /*...*/ }
}
public sealed class MyClass
{
private readonly Action somethingUnique1;
private readonly Action<TcpRequest> somethingUnique2;
public MyClass(Action somethingUnique1, Action<TcpRequest> somethingUnique2)
{
this.somethingUnique1 = somethinUnique1;
this.somethinUnique2 = somethingUnique2;
}
public void MyFunction(string apples, Action<TcpRequest> onSuccess=null, Action<TcpRequest> onError=null)
{
// Throw exception if already busy with an operation
if (!state.Has(State.Idle)) { throw new OperationInProgress(); }
// Define callback action
Action<TcpRequest> callback = delegate (TcpRequest request)
{
// Add idle state back in
state.Add(State.Idle);
// Check if the request succeeded
if (request.OK)
{
somethingUnique1();
}
// Request failed. Call the onError callback if provided
else { onError?.Invoke(request); }
};
// Remove idle state
state.Remove(State.Idle);
somethingUnique2(callback);
}
}
var variant1 = new MyClass(() => { /* ... */ }, (TcpRequest r) => { /* ... */ });
var variant2 = new MyClass(() => { /* ... */ }, (TcpRequest r) => { /* ... */ });