Nick Reshetinsky Nick Reshetinsky - 3 months ago 17
ASP.NET (C#) Question

Generics vs Base class

I'm struggling to find out the best to set up my project. I have a GameSessionServer - the class responsible for JSON request handling and the registered handlers .. Right now I have the base socket handler handler (part of class):

public WebSocketResponse HandleRequest(RequestDto request, GameSessionServer server)
{
TrySetThreadCulture(request);
EnsureUserStoredInSession(server.SessionContext, false, SlotIsEngineRNG(server.SessionContext.SystemGameId));

// custom request handling
WebSocketResponse wsr = HandleRequestInternal(request, server);

// save the last handler
server.SessionContext.Items[typeof(WebSocketHandler)] = this;
return wsr;
}


Should it be a RequestDto base class parameter or a generic RequestDto??????
In a concrete handler I do casting of the RequestDto to specific type like here:

protected override WebSocketResponse HandleRequestInternal(RequestDto request, GameSessionServer server)
{
CasinoSpinRequestDto spinRequest = request as CasinoSpinRequestDto;

int TotalBetInCents = (spinRequest.SpinType != "free") ? spinRequest.TotalBet : 0;
JsonResult JR = null;

CasinoSpinResponseDto spinResponse = new CasinoSpinResponseDto();
switch (spinRequest.SpinType)
{
case "regular":
JR = PlayBetSpin(spinRequest, server);
break;
case "free":
JR = PlayFreeSpin(spinRequest, server.SessionContext);
break;
}

// set balance in cents
spinResponse.Credit = JR.BalanceInCents;

SlotEngineRNG engineRNG;
sbyte[,] wheels = (JR is SpinJsonResult) ? ((SpinJsonResult) JR).Wheels : ((BonusJsonResult) JR).FreeSpin.Wheels;
int rsId = (JR is SpinJsonResult) ? 0 : ((BonusJsonResult) JR).FreeSpin.ReelId;

if (SlotIsEngineRNG(server.SessionContext.SystemGameId, out engineRNG))
{
GameSettingInfo gsi = DataBuffer.Instance.GetGameSetting(server.SessionContext.UserGroupId, (int) server.SessionContext.SystemGameId);
spinResponse.Results = CalculateWheelPositionsRNG( wheels , rsId , engineRNG, gsi);
} else
{
int[] pos;
PosHoldersFactory.GetSlotPositions(server.SessionContext.SystemGameId, wheels, rsId, out pos);
spinResponse.Results = pos;
}


................................

Answer

So you could use the strategy pattern:

interface IWebRequestHandler
{
    bool CanHandle(RequestDto request); // assuming the request dto is the base class

    WebSocketResponse Handle(RequestDto request, GameSessionServer server);
}

class CasinoSpinRequestHandler : IWebRequestHandler
{
    bool CanHandle(RequestDto request)
    {
        return request is CasinoSpinRequestDto;
    }

    WebSocketResponse Handle(RequestDto request, GameSessionServer server)
    {
        var spinRequest = request as CasinoSpinRequestDto;

        if (spinRequest == null) throw new ArgumentNullException("Incorrect usage of the handler");

        // do your specific spin request code here
    }
}

public WebSocketResponse HandleRequest(RequestDto request, GameSessionServer server)
{
    TrySetThreadCulture(request);
    EnsureUserStoredInSession(server.SessionContext, false, SlotIsEngineRNG(server.SessionContext.SystemGameId));

    var handlerStrategies = this.GetType().Assembly.GetTypes().Where(x => typeof(IWebRequestHandler).IsAssignableFrom(x)).Select(x => Activator.CreateInstance(x)).Cast<IWebRequestHandler>().ToList();
    // the above is poor man DI, you can just put in the constructor ctor(IEnumerable<IWebRequestHandler>)
    // if your DI supports it, otherwise you can abstract the code above to a 
    // static class so it only gets called once.

    var handler = handlerStrategies.FirstOrDefault(x => x.CanHandle(request));

    if (handler == null) throw new Exception("Unable to handle this particular request");

    // custom request handling
    var wsr = handler.Handle(request, server);

    // the consuming of the handler can also be abstracted to a delegate class
    // which merely has the responsibility of sorting out which handler to use

    // save the last handler
    server.SessionContext.Items[typeof(WebSocketHandler)] = this;
    return wsr;
}

If you need more clarification, just be specific about which part.