如何强制实施嵌套 class 属性?
How to enforce implementation of nested class properties?
我正在尝试在 Blazor WASM 中实现我自己的多语言功能。没什么特别的,但我想确保我不会忘记用特定语言实现属性。在 TypeScript 中,这适用于键入或接口对象。在 C# 中,此类对象的等效项是 class。我尝试在 C# 中使用接口和抽象 classes,但没有得到想要的结果。
期望的结果是我的代码编辑器在我忘记实现 属性 时提示。我该如何进行?
我可以将所有属性直接放入 Translation
class 中以强制执行它们,但是我会有一个很长的属性列表,我宁愿将它们切碎位.
public class NavMenuProps
{
public string FirstMenuHeader { get; set; } = "Dogs";
public string SecondMenuHeader { get; set; } = "Facilities";
public string ThirdMenuHeader { get; set; } = "Profile";
}
public abstract class Translation
{
public abstract NavMenuProps NavMenu();
}
public class English : Translation
{
public override NavMenuProps NavMenu()
{
return new NavMenuProps();
}
}
public class Dutch : Translation
{
public override NavMenuProps NavMenu()
{
return new NavMenuProps
{
FirstMenuHeader = "Honden",
SecondMenuHeader = ""
};
}
}
public class French : Translation
{
public override NavMenuProps NavMenu()
{
throw new System.NotImplementedException();
}
}
在 TypeScript 中它会像这样工作:
type TNavMenuProps = {
firstMenuHeader: string;
secondMenuHeader: string;
thirdMenuHeader: string;
...
}
type TLoginPageProps = {
firstLabel: string;
secondLabel: string;
...
}
type TTranslation = {
navMenu: TNavMenuProps;
loginPage: TLoginPageProps;
...
}
const englishTranslations: TTranslation = {
navMenu: {
firstMenuHeader: "first";
secondMenuHeader: "second";
// Would complain I forgot "thirdMenuHeader".
},
loginPage: {
firstLabel: "1st label";
secondLabel: "2nd label";
},
...
}
如果我正确理解了您的要求,这可能是一种方法:制作 NavMenuProps
abstract
,并在 Translation
中实现 NavMenu()
。现在,与其在继承 Translation
的所有 类 中实现 NavMenu()
,不如在所有 类 中实现 NavMenuProps
中的所有属性。
public abstract class NavMenuProps
{
public abstract string FirstMenuHeader { get; }
public abstract string SecondMenuHeader { get; }
public abstract string ThirdMenuHeader { get; }
}
public abstract class Translation : NavMenuProps
{
public Translation NavMenu() => this;
}
public class English : Translation
{
public override string FirstMenuHeader => "First";
public override string SecondMenuHeader => "Second";
public override string ThirdMenuHeader => "Third";
}
现在可以打电话了
var englishMenu = new English().NavMenu();
如果需要以任何其他方式为某些 类 实现 NavMenu()
,您可以实现 virtual
并在需要的地方覆盖它:
public abstract class Translation : NavMenuProps
{
public virtual Translation NavMenu() => this;
}
public class English : Translation
{
//...
public override Translation NavMenu()
{
//return base.NavMenu();
}
}
如果我理解你的要求,这就是解决方案
将 NavMenu 属性声明为接口
public interface NavMenuProps
{
public string FirstMenuHeader { get; set; }
public string SecondMenuHeader { get; set; }
public string ThirdMenuHeader { get; set; }
}
将翻译 class 声明为具有抽象属性的抽象
public abstract class Translation : NavMenuProps
{
public abstract string FirstMenuHeader { get; set; }
public abstract string SecondMenuHeader { get; set; }
public abstract string ThirdMenuHeader { get; set; }
}
现在您可以实现每种语言的翻译,如果您不实现任何语言的 NavMenuProps 属性class,代码编辑器会抱怨“没有实现继承的抽象成员”
public class English : Translation
{
public override string FirstMenuHeader { get; set; }
public override string SecondMenuHeader { get; set; }
public override string ThirdMenuHeader { get; set; }
}
public class Dutch : Translation
{
public override string FirstMenuHeader { get; set; }
public override string SecondMenuHeader { get; set; }
public override string ThirdMenuHeader { get; set; }
}
public class French : Translation
{
public override string FirstMenuHeader { get; set; }
public override string SecondMenuHeader { get; set; }
public override string ThirdMenuHeader { get; set; }
}
(代答题者,移至答案部分).
该解决方案并不比只有一个巨大的界面好多少,但它满足了我的需要,即具有可管理的界面并且 IDE 告诉我何时忘记实现一个字段。
受已接受答案启发的解决方案:
public interface INavMenuProps
{
public string FirstMenuHeader { get; set; }
public string SecondMenuHeader { get; set; }
public string ThirdMenuHeader { get; set; }
}
public interface ILoginPageProps
{
public string FirstLabel { get; set; }
public string SecondLabel { get; set; }
}
public interface Translation : INavMenuProps, ILoginPageProps
{
}
public class English : Translation
{
public string FirstMenuHeader { get; set; } = "Dogs";
public string SecondMenuHeader { get; set; } = "Facilities";
public string ThirdMenuHeader { get; set; } = "Profile";
public string FirstLabel { get; set; } = "1st label";
public string SecondLabel { get; set; } = "2nd label";
}
public class Dutch : Translation
{
}
public class French : Translation
{
}
我正在尝试在 Blazor WASM 中实现我自己的多语言功能。没什么特别的,但我想确保我不会忘记用特定语言实现属性。在 TypeScript 中,这适用于键入或接口对象。在 C# 中,此类对象的等效项是 class。我尝试在 C# 中使用接口和抽象 classes,但没有得到想要的结果。
期望的结果是我的代码编辑器在我忘记实现 属性 时提示。我该如何进行?
我可以将所有属性直接放入 Translation
class 中以强制执行它们,但是我会有一个很长的属性列表,我宁愿将它们切碎位.
public class NavMenuProps
{
public string FirstMenuHeader { get; set; } = "Dogs";
public string SecondMenuHeader { get; set; } = "Facilities";
public string ThirdMenuHeader { get; set; } = "Profile";
}
public abstract class Translation
{
public abstract NavMenuProps NavMenu();
}
public class English : Translation
{
public override NavMenuProps NavMenu()
{
return new NavMenuProps();
}
}
public class Dutch : Translation
{
public override NavMenuProps NavMenu()
{
return new NavMenuProps
{
FirstMenuHeader = "Honden",
SecondMenuHeader = ""
};
}
}
public class French : Translation
{
public override NavMenuProps NavMenu()
{
throw new System.NotImplementedException();
}
}
在 TypeScript 中它会像这样工作:
type TNavMenuProps = {
firstMenuHeader: string;
secondMenuHeader: string;
thirdMenuHeader: string;
...
}
type TLoginPageProps = {
firstLabel: string;
secondLabel: string;
...
}
type TTranslation = {
navMenu: TNavMenuProps;
loginPage: TLoginPageProps;
...
}
const englishTranslations: TTranslation = {
navMenu: {
firstMenuHeader: "first";
secondMenuHeader: "second";
// Would complain I forgot "thirdMenuHeader".
},
loginPage: {
firstLabel: "1st label";
secondLabel: "2nd label";
},
...
}
如果我正确理解了您的要求,这可能是一种方法:制作 NavMenuProps
abstract
,并在 Translation
中实现 NavMenu()
。现在,与其在继承 Translation
的所有 类 中实现 NavMenu()
,不如在所有 类 中实现 NavMenuProps
中的所有属性。
public abstract class NavMenuProps
{
public abstract string FirstMenuHeader { get; }
public abstract string SecondMenuHeader { get; }
public abstract string ThirdMenuHeader { get; }
}
public abstract class Translation : NavMenuProps
{
public Translation NavMenu() => this;
}
public class English : Translation
{
public override string FirstMenuHeader => "First";
public override string SecondMenuHeader => "Second";
public override string ThirdMenuHeader => "Third";
}
现在可以打电话了
var englishMenu = new English().NavMenu();
如果需要以任何其他方式为某些 类 实现 NavMenu()
,您可以实现 virtual
并在需要的地方覆盖它:
public abstract class Translation : NavMenuProps
{
public virtual Translation NavMenu() => this;
}
public class English : Translation
{
//...
public override Translation NavMenu()
{
//return base.NavMenu();
}
}
如果我理解你的要求,这就是解决方案
将 NavMenu 属性声明为接口
public interface NavMenuProps
{
public string FirstMenuHeader { get; set; }
public string SecondMenuHeader { get; set; }
public string ThirdMenuHeader { get; set; }
}
将翻译 class 声明为具有抽象属性的抽象
public abstract class Translation : NavMenuProps
{
public abstract string FirstMenuHeader { get; set; }
public abstract string SecondMenuHeader { get; set; }
public abstract string ThirdMenuHeader { get; set; }
}
现在您可以实现每种语言的翻译,如果您不实现任何语言的 NavMenuProps 属性class,代码编辑器会抱怨“没有实现继承的抽象成员”
public class English : Translation
{
public override string FirstMenuHeader { get; set; }
public override string SecondMenuHeader { get; set; }
public override string ThirdMenuHeader { get; set; }
}
public class Dutch : Translation
{
public override string FirstMenuHeader { get; set; }
public override string SecondMenuHeader { get; set; }
public override string ThirdMenuHeader { get; set; }
}
public class French : Translation
{
public override string FirstMenuHeader { get; set; }
public override string SecondMenuHeader { get; set; }
public override string ThirdMenuHeader { get; set; }
}
(代答题者,移至答案部分).
该解决方案并不比只有一个巨大的界面好多少,但它满足了我的需要,即具有可管理的界面并且 IDE 告诉我何时忘记实现一个字段。
受已接受答案启发的解决方案:
public interface INavMenuProps
{
public string FirstMenuHeader { get; set; }
public string SecondMenuHeader { get; set; }
public string ThirdMenuHeader { get; set; }
}
public interface ILoginPageProps
{
public string FirstLabel { get; set; }
public string SecondLabel { get; set; }
}
public interface Translation : INavMenuProps, ILoginPageProps
{
}
public class English : Translation
{
public string FirstMenuHeader { get; set; } = "Dogs";
public string SecondMenuHeader { get; set; } = "Facilities";
public string ThirdMenuHeader { get; set; } = "Profile";
public string FirstLabel { get; set; } = "1st label";
public string SecondLabel { get; set; } = "2nd label";
}
public class Dutch : Translation
{
}
public class French : Translation
{
}