我有遗留的代码,我试图淘汰,我无法改变。它是一个基于列的数据存储类,可以根据列的名称编制索引。像这样:
StorageClassName scn = new StorageClassName("Property_Name",new double[]{1,2,3});
double[] d = scn["Property_Name"];
我正在尝试创建某种包装类,它允许我实现接口/类继承。
BetterStorageClassName bscn = scn;
double[] d = bscn.PropertyName;
完成此包装类的最佳方法是什么?它不一定需要隐含。
编辑:我放弃了这个问题的主要部分。我在第一部分得到的答案虽然很好。我将如何以其他方式进行转换?
double[] d = bscn["PropertyName"];
我假设这在某种程度上使用了反射。
答案 0 :(得分:2)
如果您有一个包含字符串索引器的类,并且您想将其转换为属性,则可以使用dynamic
执行此操作:
class StorageClassName : Dictionary<string, double[]>
{}
class DynamicStorageClassName : DynamicObject
{
private readonly StorageClassName m_storageClassName;
public DynamicStorageClassName(StorageClassName storageClassName)
{
m_storageClassName = storageClassName;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (m_storageClassName.ContainsKey(binder.Name))
{
result = m_storageClassName[binder.Name];
return true;
}
return base.TryGetMember(binder, out result);
}
}
用法:
var scn = new StorageClassName { { "PropertyName", new double[] { 1, 2, 3 } } };
dynamic dscn = new DynamicStorageClassName(scn);
Console.WriteLine(dscn.PropertyName[1]);
请注意,使用dynamic
会对性能造成一定的损失,如果属性集不会改变,则应该像其他人建议的那样使用普通属性。
另一方面,如果您有一个具有普通属性的类并希望将其转换为使用索引器,则可以使用反射:
class StaticStorageClassName
{
public double[] PropertyName { get; set; }
public StaticStorageClassName()
{
PropertyName = new double[] { 1, 2, 3 };
}
}
class ReverseStorageClassName
{
private readonly StaticStorageClassName m_staticStorageClassName;
public ReverseStorageClassName(StaticStorageClassName staticStorageClassName)
{
m_staticStorageClassName = staticStorageClassName;
}
public double[] this[string name]
{
get
{
var propertyInfo = typeof(StaticStorageClassName).GetProperty(name);
if (propertyInfo == null)
throw new ArgumentException();
return (double[])propertyInfo.GetValue(m_staticStorageClassName, null);
}
}
}
用法:
var sscn = new StaticStorageClassName();
var rscn = new ReverseStorageClassName(sscn);
Console.WriteLine(rscn["PropertyName"][2]);
如果各种属性具有不同的类型,则必须使索引器的返回类型为object
或dynamic
。
请注意,如果使用StaticStorageClassName
实现DynamicObject
,则无法使用反射。
答案 1 :(得分:1)
对于给出的示例,我认为它的实现方式如下:
public double[] PropertyName
{
get { return wrapped["Property_Name"]; }
set { wrapped["Property_Name"] = value; }
}
您是否试图避免编写所有这些包装器?或者进行类型转换?
答案 2 :(得分:1)
从您的问题我想你想要完整的命名属性而不是基于字符串的键。在这种情况下,您只需提供访问属性:
class BetterStorageClassName : StorageClassName
{
public double[] PropertyName
{
get { return this["Property_Name"]; }
set { this["Property_Name"] = value; }
}
}
然而,该方法有几点需要注意: