Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/288.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#使用索引设置属性_C#_Coding Style_Properties - Fatal编程技术网

C#使用索引设置属性

C#使用索引设置属性,c#,coding-style,properties,C#,Coding Style,Properties,我有一个业务类,它包含各种证券交易所价格类型的许多属性。这是该类的一个示例: public class Prices { public decimal Today {get; set;} public decimal OneDay {get; set;} public decimal SixDay {get; set;} public decimal TenDay {get; set;} public decimal TwelveDay {get; set

我有一个业务类,它包含各种证券交易所价格类型的许多属性。这是该类的一个示例:

public class Prices
{
    public decimal Today {get; set;}
    public decimal OneDay {get; set;}
    public decimal SixDay {get; set;}
    public decimal TenDay {get; set;}
    public decimal TwelveDay {get; set;}
    public decimal OneDayAdjusted {get; set;}
    public decimal SixDayAdjusted {get; set;}
    public decimal TenDayAdjusted {get; set;}
    public decimal OneHundredDayAdjusted {get; set;}
}
我有一个遗留系统,它使用字符串ID来标识价格类型来提供价格

例如

Today = "0D"  
OneDay = "1D"  
SixDay = "6D"  
//..., etc.   
首先,我将所有值加载到IDictionary()集合,因此我们有:

[键]值
[0D]=>1.23456
[1D]=>1.23456
[6D]=>1.23456
等等

其次,我使用将上述集合作为参数的方法设置Prices类的属性,如下所示:

SetPricesValues(IDictionary<string, decimal> pricesDictionary)  
{  
    // TODAY'S PRICE  
    string TODAY = "D0";  
    if (true == pricesDictionary.ContainsKey(TODAY))  
    {  
        this.Today = pricesDictionary[TODAY];  
    }  
    // OneDay PRICE  
    string ONE_DAY = "D1";  
    if (true == pricesDictionary.ContainsKey(ONE_DAY))  
    {  
         this.OneDay = pricesDictionary[ONE_DAY];  
    }  
//..., ..., etc., for each other property   
}  
setpricesvalue(IDictionary pricesDictionary)
{  
//今天的价格
string TODAY=“D0”;
if(true==pricesDictionary.ContainsKey(今天))
{  
this.Today=价格指数[今天];
}  
//单日价格
字符串1_DAY=“D1”;
if(true==pricesDictionary.ContainsKey(一天))
{  
this.OneDay=价格折扣[一天];
}  
//…,…,等等,为彼此的财产
}  
有没有更优雅的方法来设置大量属性? 谢谢
j

我会将字符串变量放入常量中,而不是每次运行该方法时都声明它们:

private const string ONE_DAY = "D1";

如果您希望collection参数包含所有或大部分可能的值,那么您的代码可能很酷。如果您希望字典将有一小部分可能的值,那么使用foreach循环和switch语句来设置值可能会更有效,而不是每次都查找每个可能的值。这取决于您需要处理多少值以及每次方法调用中得到多少值。

在我看来,您有一些选择,具体取决于您的技能、允许您更改当前POCO或其他类的方式:

  • 如果必须使用字典,请创建一个类似的字典,将“0D”等映射到某一天的名称。循环浏览字典并使用简单反射进行赋值
  • 如果可以更改读取数据的方式,请使用OneDay等来读取字典,而不是仅适用于外部应用程序的“0D”
  • 创建一个属性,
    LegacyKeyAttribute
    ,用该属性扩充您的POCO gettor/setors。现在它变得很简单:通过循环POCO的属性来找到当前遗留密钥的正确属性
最后一个选项需要比许多普通程序员所知道的更多地理解C语言:编写和使用属性和反射。然而,最终它是最干净、最简单的解决方案(我将尝试给出一个示例)


更新:这里有一个小例子。同时,已经发布了许多改进建议,但没有一个仍然使用属性,而您的案例似乎很理想。为什么?我相信,它对现有代码造成的负担最小,并且使阅读和理解代码更加容易

用法:

// any price:
Prices prices = new Prices();
prices.SetPriceByLegacyName("0D", 1.2345M);

// or, your loop becomes a bit easier:
SetPricesValues(IDictionary<string, decimal> pricesDictionary)  
{  
    foreach(string key in pricesDictionary.Keys)
    {
        // assuming "this" is of type Prices (you didn't specify)
        this.SetPriceByLegacyName(key, pricesDictionary[key]);
    }    
}  
就这些。即使添加了所有行,也可能是总行数变少了。但更重要的是,它变得更易于维护和使用。

这只是一个想法:

interface IPrices_As_String{
 string OD { get; set; }
 // other properties here...
}

interface IPrices{
 decimal Today{get; set;}
}

class Prices : IPrices, IPrices_As_String{
 public decimal Today { get; set; }
 public string IPrices_As_String.OD {
  get { return this.Today.ToString(); }
  set { 
    if(!String.IsNullOrEmpty(value)){
       this.Today = decimal.Parse(value);
    }
  }
 }
}
然后,当我从遗留系统设置值时,我将使用接口上的Prices类作为IPrices_作为_字符串,如下所示:

IPrices_As_String obj = new Prices();
// set values from the legacy system

IPrices obj2 = obj as IPrices; // will give me the correct object..


HTH.

在构造函数中定义属性字典,例如

private Dictionary<int, PropertyInfo> propertyDictionary = new ...

MyClass()
{
    this.propertyDictionary.Add(0, this.GetType().GetProperty("FirstProperty");
    ...
}
稍后,您可以通过使用反射自动解析构造函数中的属性来改进此代码, 添加具有告诉您id是什么的属性的所有属性。
(不要在构造函数中手动添加它们)。

不要使用字符串到十进制的映射并反复检查字典,而是使用委托映射/扩展方法:

public static class PriceConverter
{
    private static readonly Dictionary<string, Action<Prices, decimal>> setters =
        CreateSetterDictionary();

    public static void SetPrice(this Prices p, string id, decimal newPrice)
    {
        Action<Prices, decimal> setter;
        if (setters.TryGetValue(id, out setter))
            setter(p, newPrice);
    }

    private static Dictionary<string, Action<Prices, decimal>>
        CreateSetterDictionary()
    {
        var dic = new Dictionary<string, Action<Prices, decimal>>();
        dic.Add("0D", (p, d) => p.Today = d);
        dic.Add("1D", (p, d) => p.OneDay = d);
        // etc.
        return dic;
    }
}
公共静态类价格转换器
{
专用静态只读字典设置程序=
CreateSetterDictionary();
公共静态void SetPrice(此价格为p,字符串id,十进制newPrice)
{
行动设定者;
if(setters.TryGetValue(id,out setter))
setter(p,newPrice);
}
专用静态字典
CreateSetterDictionary()
{
var dic=新字典();
加上(“0D”,(p,d)=>p.今天=d);
加上(“1D”,(p,d)=>p.OneDay=d);
//等等。
返回dic;
}
}
然后您可以编写
prices.SetPrice(“0D”,1.23456)


如果愿意,请在
SetPrice
方法的末尾添加
throw
语句,以处理
id
不匹配的情况。

如果(true==something\u或其他),请不要编写
。<代码>真==<代码>是完全多余的,伤害了人们的眼睛。有些人可能认为它更清晰。虽然我同意你的观点,但它不会伤害我的眼睛(我见过更糟糕的代码,它应该被称为“伤害”);-)@亚伯:按照你的逻辑,(真==(真==foo))不是更清楚吗?你也可以为了无限的清晰而无限地继续它!哈哈,我不认为我自己更清楚,但是有些人做了(为什么不<代码>!false = =包容键())/>代码>。同样,他们可能会使用
==false
而不是
其他
。但是代码中还有一些明显的地方需要注意,这就是为什么Guazz提出了这个问题,我想:)索引可以是int/String/WhateverI,我不认为这会让它变得更容易。您仍然需要至少与他当前的实现一样多的代码来设置值,除非您使用反射,在这种情况下,您可以只使用属性或映射数组在字符串键和字段之间进行映射。@Matti-可能我遗漏了什么,但我没有使用任何反射-我直接设置属性&在集合中,将字符串转换为所需的相关类型…
stringod{get;set;}
:您编写了一个
O
,而不是
0
,但请再次查看原始代码段:这些前缀是数字。及
decimal this[int index]
{
    get
    {
        PropertyInfo property;
        if (this.propertyDictionary.TryGetValue(index, out property))
        {
            // Not sure I remember the arguments right here:
            property.SetValue(this, new object[] { value });
        }
    set
    {
        // Similar code
    }
}
public static class PriceConverter
{
    private static readonly Dictionary<string, Action<Prices, decimal>> setters =
        CreateSetterDictionary();

    public static void SetPrice(this Prices p, string id, decimal newPrice)
    {
        Action<Prices, decimal> setter;
        if (setters.TryGetValue(id, out setter))
            setter(p, newPrice);
    }

    private static Dictionary<string, Action<Prices, decimal>>
        CreateSetterDictionary()
    {
        var dic = new Dictionary<string, Action<Prices, decimal>>();
        dic.Add("0D", (p, d) => p.Today = d);
        dic.Add("1D", (p, d) => p.OneDay = d);
        // etc.
        return dic;
    }
}