6

私の CTO (最高技術責任者) は、基本クラスに 1 つの関数を記述し、子クラスのすべてのプロパティにアクセスできるようにする方法を考え出すように私に依頼しました。これが私が思いついたものです-

基本クラス

class Assets
{
    public Assets getPropertyVal(Assets asObj)
    {
        PropertyInfo[] propInfos = asObj.GetType().GetProperties();
        string strAttributeValue = "10";
        foreach (PropertyInfo propInfo in propInfos)
        {
            // Getting the value
            var propValue = propInfo.GetValue(asObj, null);

            // Setting the value
            propInfo.SetValue(asObj, Convert.ChangeType(strAttributeValue, propInfo.PropertyType), null);

        }
        return asObj;
    }
}

子クラス

class House : Assets
{
    public int rooms{get; set;}
}

Program.cs ファイル

class Program
{
    static void Main(string[] args)
    {
        House hsObj = new House();
        hsObj.rooms = 5;

        Assets asObj = hsObj.getPropertyVal(hsObj);
        // Returns asObj as JSON
    }
}

これで問題なく動作しますが、C# でこれを行うためのより良い方法があるかどうか疑問に思っていました。

子クラスに存在するプロパティがわからないため、実行時に決定する必要があることに注意してください。

更新明確にするために、リフレクションを使用せずに子クラスのプロパティにアクセスするより良い方法があるかどうか疑問に思っていました。注意すべき重要な点は、子クラスが持つ可能性のあるプロパティがわからないということです。

更新 #2 : 多くのエンティティを持つ製品を使用しています。これらのエンティティには異なるプロパティがあります。これらすべてのプロパティに 1 か所でアクセスして操作できるようにしたいと考えています。この機能はまさにそれです。すべてのデータにアクセスできる 1 つの場所です。

4

2 に答える 2

6

まず、あなたの Program.cs は、あなたが望んでいることを実際には "実行" しません。これを行うためのプログラムが必要なようです。

Asset myAsset = new House();
myAsset.Rooms = 5;

しかし、とにかくそれをしたいのはなぜですか?アセットがハウスでない場合、例外がスローされるため、最初にそれを確認する必要があります。

if (myAsset is House)
    myAsset.Rooms = 5;

その時点で、ハウスにキャストすることもできます。継承の代わりに PropertyBag または Dictionary を使用したい場合があるようです。

あなたが説明しているのはこれだと思います。オプション1は、どのクラスでどのプロパティを使用できるかを実際には制限していないことに注意してください。したがって、これは特定のケースでは実際には機能しないと思います。

// Option 1, a Property Bag (Note: this replaces the properties on the classes)
class Asset
{
    Dictionary<string, object> myPropertyBag = new Dictionary<string, object>();

    public T GetProperty<T>(string property)
    {
        // This throws if the property doesn't exist
        return (T)myPropertyBag[property];
    }

    public void SetProperty<T>(string property, T value)
    {
        // This adds the property if it doesn't exist
        myPropertyBag[property] = (object)value;
    }
}

// Option 2, use a switch and override this function in derived classes
class Asset
{
    public int SomePropertyOnAsset { get; set; }

    public virtual T GetProperty<T>(string property)
    {
        switch (property)
        {
            case "SomePropertyOnAsset": return this.SomePropertyOnAsset;

            default: throw new ArgumentException("property");
        }
    }

    public virtual void SetProperty<T>(string property, T value)
    {
        switch (property)
        {
            case "SomePropertyOnAsset": this.SomePropertyOnAsset = (int)value;

            default: throw new ArgumentException("property");
        }
    }
}

class House : Asset
{
    public int Rooms { get; set; }

    public virtual T GetProperty<T>(string property)
    {
        switch (property)
        {
            case "Rooms": return this.Rooms;

            default: return base.GetProperty<T>(property);
        }
    }

    public virtual void SetProperty<T>(string property, T value)
    {
        switch (property)
        {
            case "Rooms": this.Rooms = (int)value; 
                break;

            default: base.SetProperty<T>(property, value);
                break;
        }
    }
}

次に、これを使用する方法は次のとおりです。

// Option 1
Asset asset = new House();
asset.SetProperty("Rooms", 5);
var rooms = asset.GetProperty<int>("Rooms");

// Option 2
Asset asset = new House();
asset.SetProperty("Rooms", 5);
asset.SetProperty("SomePropertyOnAsset", 10);
asset.SetProperty("SomethingElse", 15); // Throws ArgumentException

3 番目のオプションは、Asset を DynamicObject にすることです。 http://msdn.microsoft.com/en-us/library/system.dynamic.dynamicobject.aspx

Asset 基底クラスに大きな変更を加えたり、すべてのエンティティに触れたりすることができない、またはしたくない場合は、おそらくリフレクションを使用する必要があります。

于 2013-07-30T18:32:33.377 に答える
1

ルーク・グラビットはおそらく正しいでしょう。家にキャストしたいだけかもしれません。

House myHouse = asObj as House;
if ( myHouse != null )
{
  // do some fun house stuff
}

Yacht myYacht = asObj as Yacht;
if ( myYacht != null )
{
   // put on monocle
}
于 2013-07-31T11:27:22.237 に答える