C
C#3w ago
Core

✅ Best approach for returning typed objects

Hello, I am porting a popular UA parser library called DeviceDetector to .NET. The library determines the client from the user agent, which can be a browser, media player, feed reader, etc. With the current implementation, there is an interface that all client models implement, and the returned object after parsing is of type IClientInfo. This means that users would need to perform type checking and casting to determine the exact client type. As I see it, there are two possibilities, each providing the user with a different way of handling the concrete client. Which of these approaches would be the best to follow? 1st approach
c#
public interface IClientInfo
{
string Name { get; init; }
string? Version { get; init; }
}

public sealed class BrowserInfo : IClientInfo
{
public string Name { get; init; }
public string? Version { get; init; }
public BrowserCode Code { get; init; }
public string? Family { get; init; }
public string? Engine { get; init; }
public string? EngineVersion { get; init; }
}


// handling client after parsing
var result = DeviceDetector.Parse(userAgent);

if (result.Client is BrowserInfo browser)
{

}
c#
public interface IClientInfo
{
string Name { get; init; }
string? Version { get; init; }
}

public sealed class BrowserInfo : IClientInfo
{
public string Name { get; init; }
public string? Version { get; init; }
public BrowserCode Code { get; init; }
public string? Family { get; init; }
public string? Engine { get; init; }
public string? EngineVersion { get; init; }
}


// handling client after parsing
var result = DeviceDetector.Parse(userAgent);

if (result.Client is BrowserInfo browser)
{

}
2nd approach - it's similar to the 1st approach, but it is extended with an enum that represents the concrete type
c#
public interface IClientInfo
{
ClientType Type {get; init; }
string Name { get; init; }
string? Version { get; init; }
}

public sealed class BrowserInfo : IClientInfo
{
public ClientType Type {get; init; }
public string Name { get; init; }
public string? Version { get; init; }
public BrowserCode Code { get; init; }
public string? Family { get; init; }
public string? Engine { get; init; }
public string? EngineVersion { get; init; }
}

var result = DeviceDetector.Parse(userAgent);

// handling client after parsing
if (result.Client.Type == ClientType.Browser)
{
var browser = (BrowserInfo)result.Client;
}
c#
public interface IClientInfo
{
ClientType Type {get; init; }
string Name { get; init; }
string? Version { get; init; }
}

public sealed class BrowserInfo : IClientInfo
{
public ClientType Type {get; init; }
public string Name { get; init; }
public string? Version { get; init; }
public BrowserCode Code { get; init; }
public string? Family { get; init; }
public string? Engine { get; init; }
public string? EngineVersion { get; init; }
}

var result = DeviceDetector.Parse(userAgent);

// handling client after parsing
if (result.Client.Type == ClientType.Browser)
{
var browser = (BrowserInfo)result.Client;
}
3 Replies
ACiDCA7
ACiDCA73w ago
if i interpret your question correctly, you are determining the type during runtime. if thats the case there is no way. think a bit further, how would the implementer/compiler know which type to use? so they have to do the typechecking and cast appropriatly
Core
CoreOP3w ago
Thanks, what about the design? Should I include an enum that represents the client type?
ACiDCA7
ACiDCA73w ago
sounds resonable, maybe even include the version in the enum in case of multiple types that differ in api during versioning

Did you find this page helpful?