对于具有外部set/get方法的强类型类成员,是否有C#模式?

Sim*_*eon 20 .net c# c#-4.0

我有以下结构,并希望解决方案同时受益于以下两个类.第一个类使用字符串和强类型成员:

public class UserSessionData
{
    private string Get(string key)
    {
        throw new NotImplementedException("TODO: Get from external source");
    }
    private void Set(string key, string value)
    {
        throw new NotImplementedException("TODO: Set in external source");
    }

    public string CustomerNumber {
        get { return Get("CustomerNumber"); }
        set { Set("CustomerNumber", value); }
    }
    public string FirstName {
        get { return Get("FirstName"); }
        set { Set("FirstName", value); }
    }
    public string LastName {
        get { return Get("LastName"); }
        set { Set("LastName", value); }
    }

    // ... a couple of hundreds of these
}
Run Code Online (Sandbox Code Playgroud)

我可以想像一种替代是一个GetSet方法用enum参数.这是第二堂课:

public class UserSessionData
{
    public enum What {
        CustomerNumber, FirstName, LastName, // ...
    }

    public string Get (What what) { return MyExternalSource(what); }
    public string Set (What what, string value) { return MyExternalSource(what); }
}
Run Code Online (Sandbox Code Playgroud)

但是#2类的消费者方面并不漂亮:
UserSessionData.Get(UserSessionData.What.CustomerNumber)
将它与第一类比较:UserSessionData.CustomerNumber

在我的第一个类示例中是否有一种强类型的方法来调用Get和Set方法?换句话说:如何从两个类中获益,即强类型成员的可维护性和漂亮的语法?

lig*_*cko 34

.Net 4.5或更新版本

如果你使用.Net 4.5或更新版本,你可以使用CallerMemberNameAttribute,这样就可以像这样调用它:

public string CustomerNumber {
    get { return Get(); }
}
Run Code Online (Sandbox Code Playgroud)

要使其工作,请通过向参数添加属性来修改Get方法:

private string Get([CallerMemberName] string key)
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

性能提示:编译器会在调用站点插入一个字符串作为参数,因此速度很快.


.Net 4.0或更早版本

如果您使用.NET 4.0或更早版本,您仍然可以使用强类型属性名称,而不是手动输入的字符串,但你需要实现一个方法,像这样从一个提取属性的名称表达,然后你可以使用表达式叫它:

public string CustomerNumber {
    get { return Get(() => this.CustomerNumber ); }
}
Run Code Online (Sandbox Code Playgroud)

设置器可以以相同的方式实现.

性能提示:字符串在运行时提取,因此比使用CallerMemberNameAttribute慢.

  • @Gusdor表达式树不是预编译的,它们每次都是构造的.比较贵.即使你摆脱了外部依赖(如lightbricko的例子中的`this`). (2认同)

Ale*_*lex 8

您可以使用T4模板生成类.在T4模板中,您只需命名所有属性 - 您也可以通过枚举的反射来获取它们,但使用字符串数组更简单.

添加新项目 - >文本模板

<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ output extension=".cs" #>
<# var properties = new string [] {
      "CustomerNumber", // This is where you define the properties
      "FirstName",
      "LastName"
}; #>
class UserSessionData {
<#  
  foreach (string propertyName in properties) 
  { #>
  public string <#= propertyName #>{
    get { return Get("<#= propertyName #>"); }
    set { Set("<#= propertyName #>", value); }
  }
<# } #>
}
Run Code Online (Sandbox Code Playgroud)

更多信息@ 使用T4文本模板生成设计时代码

  • @GSerg在这种情况下,它们仅在模板中列出一次.如果您需要更改类,只需编辑模板即可.另外,就像我说的,你可以使用enum,如果你必须的话. (2认同)
  • 是的,但错误的方式无法编译.这不是运行时绑定,这仍然得到了正确的编译,同时支持完整的Intellisense.真的不能要求更多(如果您编写的是4.5,那么除了魔法属性). (2认同)