3

これは汚いことであり、私はそれを行うことに汚いと感じています:

public abstract class InterestRate {

    // irrelevant details

    public static T ImpliedRate<T>(
        double factor,
        double time,
        DayCounter dayCounter
    ) where T : NonCompoundedInterestRate {
        MethodInfo methodInfo = typeof(T).GetMethod(
            "ImpliedRate",
            BindingFlags.Static);
        return (T)methodInfo.Invoke(
            null,
            new object[] { factor, time, dayCounter }
        );
    }

    public static T ImpliedRate<T>(
        double factor,
        double time,
        DayCounter dayCounter,
        Frequency frequency
    ) where T : CompoundedInterestRate {
        MethodInfo methodInfo = typeof(T).GetMethod(
            "ImpliedRate",
            BindingFlags.Static);
        return (T)methodInfo.Invoke(
            null,
            new object[] { factor, time, dayCounter, frequency }
        );
}

ここにクラスNonCompoundedInterestRate(抽象)がありCompoundedInterestRate、抽象クラスから派生していInterestRateます。上記のリフレクションが機能するための適切なシグネチャで名前がNonCompoundedInterestRate付けられた静的メソッドを持ついくつかの具体的な実装があります。ImpliedRate

リフレクションを使用して、派生クラスにあることが保証されていない静的メソッドを呼び出すと、悪臭がします。これを処理するより良い方法はありますか?

4

6 に答える 6

2

汚いと感じるはずです。ここにいくつかの石鹸があります:

public static class InterestRateFactories
{
    static InterestRateFactories()
    {
        _factories = new List<IInterestRateFactory>();
        //  register default factories, although you can also register them elsewhere, like in your ioc setup
    }
    private static readonly List<IInterestRateFactory> _factories;
    public static void RegisterFactory(IInterestRateFactory factory)
    {
        _factories.Add(factory);
    }
    public static T ImpliedRate<T>(double factor, double time, DayCounter dayCounter)
        where T : NonCompoundedInterestRate
    {
        var factory = _factories.FirstOrDefault(x => x.CanCreate(typeof(T), false));
        if (factory == null)
        {
            throw new NotSupportedException("Cannot create a non-compounded implied interest rate of type " + typeof(T).Name);
        }
        return (T)factory.Create(factor, time, dayCounter);
    }
    public static T ImpliedRate<T>(double factor, double time, DayCounter dayCounter, Frequency frequency)
        where T : CompoundedInterestRate
    {
        var factory = _factories.FirstOrDefault(x => x.CanCreate(typeof(T), false));
        if (factory == null)
        {
            throw new NotSupportedException("Cannot create a compounded implied interest rate of type " + typeof(T).Name);
        }
        return (T)factory.Create(factor, time, dayCounter, frequency);
    }
}

public interface IInterestRateFactory
{
    bool CanCreate(Type nonCompoundedInterestRateType, bool compounded);
    NonCompoundedInterestRate Create(double factor, double time, DayCounter dayCounter);
    CompoundInterestRate Create(double factor, double time, DayCounter dayCounter, Frequency frequency);
}
于 2011-02-14T02:01:49.433 に答える
1

静的メソッドの代わりに、通常のメソッドと、変更されたクローン/プロトタイプ パターンのようなものを使用できます。例えば:

public static class InstanceMap
{
    private static readonly Dictionary<Type,object> instances = 
        new Dictionary<Type,object>();

    public static void AddInstance(object instance)
    {
        instances[instance.GetType()] = instance;
    }

    public static T GetInstance<T>() { return (T) instances[typeof(T)]; }  
}

public interface INonCompoundedInterestRate
{
    INonCompoundedInterestRate ImpliedRate(double factor,
        double time,
        DayCounter dayCounter);
}

public class MyNonCompoundedInterestRate: INonCompoundedInterestRate
{
    public INonCompoundedInterestRate ImpliedRate(double factor,
        double time,
        DayCounter dayCounter) { /* do smth*/ }

    static MyNonCompoundedInterestRate()
    {
        InstanceMap.AddInstance(new MyNonCompoundedInterestRate());
    } 
} 

public abstract class InterestRate {
    public static T ImpliedRate<T>(
        double factor,
        double time,
        DayCounter dayCounter
    ) where T : INonCompoundedInterestRate 
    {
        return InstanceMap.GetInstance<T>().
            ImpliedRate(factor, time, dayCounter);
    }
    // ...
}
于 2009-11-10T10:51:54.407 に答える
1

私の経験では、ジェネリックのパラメーターのないコンストラクターのみをインスタンス化できます。

あなたが達成しようとしていることは、反省によってのみ行うことができます。

于 2009-11-10T12:30:14.583 に答える
1

静的(ファクトリ)メソッドと継承を混在させようとすると、常に競合が発生します。探しているポリモーフィックな動作を取得するのは困難です。同様の問題があり、現在リフレクションを使用しています。もう 1 つのオプションは、既に述べたように、静的メソッドが必要ない場合は使用しないことです。次に、テンプレート メソッドまたは継承とうまく機能するその他の戦略を使用できる場合があります。

于 2009-11-10T20:31:34.160 に答える
1

呼び出し元は、派生型を T として渡すこのメソッドを呼び出すのと同じくらい簡単に、派生クラスのファクトリ メソッドを呼び出すことができるようです。

ここでのもう少し明示的なコントラクトは、 new() 制約を T に追加し、デフォルトの ctor を呼び出してから、基本クラスで定義された Init 抽象メソッドを呼び出すことです。

factory パターンにはテスト容易性の利点がありますが、ここで使用したようにはなりません。3 番目の方法は、使用するファクトリ クラスのインスタンスを呼び出し元に渡させることです (ImpliedRate メソッドはファクトリ インターフェイスにあります)。これは、単体テストには便利ですが、API の消費者にとっては面倒かもしれません。

于 2009-11-10T05:31:27.953 に答える
0

ジェネリックベースで宣言された非ジェネリックインターフェイスでそれらを定義してから、T にキャストしない理由はありますか? 一般的な引数が渡されていません...

于 2009-11-10T05:07:23.963 に答える