Pergunta

I have a string that is used in a few places.

string portalLoginPath = $"{Request.Scheme}{Uri.SchemeDelimiter}{Request.Host}/Account/Login";

I was thinking of creating a static class with a string const to store it.

public static class StringConsts{
public const string portalPath = $"{Request.Scheme}{Uri.SchemeDelimiter}{Request.Host}/Account/Login";
}

Is there a cleaner way to do this?

I'm building in ASP.NET Core MVC

Foi útil?

Solução

In C# a string preceded by a $ is an interpolated string.

An interpolated string is a construct that both

  • declares a string literal, and,
  • asks the compiler to interpolate variables names/expressions within the string.

These two cannot be separated: I know of no way to declare the string outside of the context where the compiler will find the variables, and no way to ask for interpolation of an externally stored string in the context of a scope that has the variables of interest.

Thus, there's no way to put a $"{}" type string anywhere but within the code that uses it.


The only way to put the string elsewhere (other than embedded in the code) is to forgo interpolation.  In your case all that would be left is "/Account/Login", leaving you to use the expressions in a string.Format statement.

Outras dicas

A static class is a good idea. One thing to be careful of is that class getting cluttered with a bunch of strings, then you might have little context of what the string is actually used for.

One way to solve this is have the context in the name of the class. Instead of StringConsts, maybe call this PortalConsts (Or whatever makes the most sense). This way you can organize your strings by class so it doesn't get disorganized.

Since what you want is to interpolate, what you're describing is not a constant but a function. In that case you could use a delegate:

public delegate string PortalPathFormatFunction(string scheme, string delimiter, 
    string host);

The reason I would use a delegate instead of just Func<string, string, string, string> is that it identifies the purpose of a function and disambiguates it from other functions with the same signature.

You could then implement it something like this (naming is hard)

public static class PathFormats
{
    public static PortalPathFormatFunction GetPortalPath { get; } 
        = (scheme, delimiter, host) => $"{scheme}{delimiter}{host}/Account/Login";
}

or just

public static string GetPortalPath(string scheme, string delimiter, string host) => 
    $"{scheme}{delimiter}{host}/Account/Login";

I prefer the first one because it specifies that the function must correspond to the delegate, like a class implementing an interface. If someone changes the function so that it no longer matches the delegate, I want the compiler error there, telling them not to do that, as opposed to somewhere else.

You shouldn't just be thinking of this as "a string that needs to be shared" - "strings" are a technical definition, not part of your OO or domain model. Who, in your system, would know the portal login url? Probably some sort of LoginManager, or perhaps PortalConnection component, which could also expose this path if necessary.

Of course, with this PortalConnection, you might see that it makes more sense, from the perspective of encapsulation, to not expose that string path, but instead expose a Login() method on your PortalConnection which handles logging into the portal in one place, instead of exposing the path, which is an implementation detail - it shouldn't be the responsibility of every component in your system to know how to login.

Licenciado em: CC-BY-SA com atribuição
scroll top