0

使用しなければならないサードパーティ製の不適切な設計のライブラリがあります。
動作するすべての種類の型があり、それらをSomeType1SomeType2などと呼びます。
これらの型はどれも共通の基本クラスを共有していませんが、すべてが異なる戻り値の型を持つ Value という名前のプロパティを持っています。
私がやりたいのは、このクラスを Mixin できるようにすることだけです。そのため、concreate 型が何であるかを気にせずに、戻り型が何であるかを気にせずに呼び出すことができます (使用できますsomeType1Instance.Value) 。 だから私のコードは現在: someType2Instance.Valueobject

public interface ISomeType<V>
{
  V Value {get; set;}
}

public interface ISomeTypeWrapper
{
  object Value { get; set; }
}

public class SomeTypeWrapper<T> : ISomeTypeWrapper
    where T : ISomeType<???>
{
  T someType;

  public SomeTypeWrapper(T wrappedSomeType)
  {
    someType = wrappedSomeType
  }

  public object Value
  {
     get { return someType.Value; }
     set { someType.Value = value != null ? value : default(T); }
  }
}

public class SomeType1
{
  public int Value { get; set; }
}

public class SomeType2
{
  public string Value { get; set; }
}

問題は、オブジェクトの辞書を取得するという事実のために、実行時まで T が何であるかわからないことです。

辞書を反復処理し、リフレクションを使用して実行時に SomeWrapperType を作成できますが、それは避けたいと思います。

SomeType の concreate 型を ISomeType に混在させるにはどうすればよいですか?
V 型パラメータが何であるかを知るにはどうすればよいですか? (C++ のように typedef と decltype があればいいのに)

リフレクションの使用を最小限に抑えて、これらのクラスとインターフェイス/基本クラスを混在させるにはどうすればよいですか?

4

3 に答える 3

1

SomeTypeWrapperがSomeObjectWrapperではないのはなぜですか?

public class SomeObjectWrapper : ISomeType
{
    Object _someObject;
    PropertyInfo _valuePropertyInfo;

    public SomeObjectWrapper(Object wrappedSomeObject)
    {
        _someObject = wrappedSomeObject;
        _valuePropertyInfo = _someObject.GetType().GetProperty("Value", System.Reflection.BindingFlags.Public);
    }

    public object Value
    {
        get { return _valuePropertyInfo.GetValue(_someObject, null); }
        set { _valuePropertyInfo.SetValue(_someObject, value, null); }
    }
}
于 2010-11-02T15:56:07.367 に答える
1
于 2010-11-02T16:18:36.287 に答える
0

LinFu を使用して .NET 3.5 で編集Castle の代わりに LinFu を使用することもできます。ただし、Castle と Linfu の DynamicProxy の両方でリフレクションを使用し、コードで公開されるのではなく、ライブラリの内部に隠されるだけです。したがって、リフレクションの使用を避ける必要があるのがパフォーマンス上の問題である場合、このソリューションで実際にリフレクションを避けることはできません。その場合、私は個人的に Orsol のソリューションを選択します。

ただし、これは LinFu のダックタイピングの例です。

public interface ISomeType {
    object Value{get; set;}
}

public class SomeType1
{
  public int Value { get; set; }
}

public class SomeType2
{
  public string Value { get; set; }
}

public class SomeTypeWrapperFactory
{

    public static ISomeType CreateSomeTypeWrapper(object aSomeType)
    {
        return aSomeType.CreateDuck<ISomeType>();
    }        
}


class Program
{
    public static void Main(string[] args)
    {
        var someTypes = new object[] {
            new SomeType1() {Value=1},
            new SomeType2() {Value="test"}
        };


        foreach(var o in someTypes)
        {
            Console.WriteLine(SomeTypeWrapperFactory.CreateSomeTypeWrapper(o).Value);
        }
        Console.ReadLine();
    }
}

実行時まで SomeType の型がわからないので、私は mixin を使用しませんが、ビジター パターンを使用します (これは mixins を使用する方法に関する質問に答えないことはわかっていますが、私は投げると思いました私の2セントで)。

with .NET 4 using dynamicビジター パターンを実装するための c#4 の dynamic キーワードの使用に関するBradley Grainger の投稿 を参照してください。あなたの場合、SomeTypeの辞書からすべての「値」プロパティを読み取ると、次のように機能します。

public class SomeType1
{
  public int Value { get; set; }
}

public class SomeType2
{
  public string Value { get; set; }
}

public class SomeTypeVisitor
{
    public void VisitAll(object[] someTypes)
    {
        foreach(var o in someTypes) {
            // this should be in a try-catch block
            Console.WriteLine(((dynamic) o).Value);
        }

    }
}
class Program
{
    public static void Main(string[] args)
    {
        var someTypes = new object[] {
            new SomeType1() {Value=1},
            new SomeType2() {Value="test"}
        };

        var vis = new SomeTypeVisitor();

        vis.VisitAll(someTypes);            
    }
}
于 2010-11-04T16:03:49.593 に答える