开发者

C# Indexer on Named Property Wrapper

I have legacy code that I'm trying to obsolete that I cannot change. Its a column-based data storage class that can be indexed based on the name of the column. Something like this:

StorageClassName scn = new StorageClassName("Property_Name",new double[]{1,2,3});
double[] d = scn["Property_Name"];

I'm trying to create some sort of wrapper class that will allow me to implement interfaces/c开发者_开发百科lass inheritance.

BetterStorageClassName bscn = scn;
double[] d = bscn.PropertyName;

What is the best way to accomplish this wrapper class? It doesn't necessarily need to be implicit.

Edit: I left off the main part of this question. The answers I got for the first part are good though. How would I do the conversion the other way?

 double[] d = bscn["PropertyName"];

I'm assuming this uses reflection in some capacity.


If you have a class with string indexer and you want to translate that into properties, you could do that using 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);
    }
}

Usage:

var scn = new StorageClassName { { "PropertyName", new double[] { 1, 2, 3 } } };
dynamic dscn = new DynamicStorageClassName(scn);
Console.WriteLine(dscn.PropertyName[1]);

Keep in mind that you pay some performance penalty for using dynamic and if the set of properties won't change, you should probably use ordinary properties as others suggested.

If, on the other hand, you had a class with ordinary properties and wanted to translate that to using indexer, you can use reflection:

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);
        }
    }
}

Usage:

var sscn = new StaticStorageClassName();
var rscn = new ReverseStorageClassName(sscn);
Console.WriteLine(rscn["PropertyName"][2]);

If the various properties have different types, you'd have to make the return type of the indexer either object or dynamic.

Note that using reflection wouldn't work if StaticStorageClassName was implemented using DynamicObject.


For the example given, I would imagine it implemented like this:

public double[] PropertyName
{
    get { return wrapped["Property_Name"]; }
    set { wrapped["Property_Name"] = value; }
}

Are you trying to avoid writing all these wrappers? Or do type conversions?


From your question I guess you want to have full named properties instead of string based keys. In that case you can just provide properties for the access:

class BetterStorageClassName : StorageClassName 
{
    public double[] PropertyName
    {
        get { return this["Property_Name"]; }
        set { this["Property_Name"] = value; }
    }
}

However that method has several caveats:

  • It implies that the properties are fixed and don't really change because otherwise you end up constantly modifying your wrapper.
  • The properties can't be dynamically defined at runtime.
  • You have to have a wrapper class for each set of properties.
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜