这是一件很脏的事情,我觉得这样做很脏:
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
的静态方法,并具有相应的签名,以便上述反射可以工作。
使用反射来调用一个静态方法,该方法甚至不能保证在派生类中存在,只需要查看。有没有更好的方法来解决这个问题?
答案 0 :(得分: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);
}
答案 1 :(得分:1)
似乎调用者可以轻松地在派生类上调用工厂方法,因为调用此方法将派生类型作为T传递。
这里稍微更明确的合同是向T添加new()约束,调用默认ctor,然后调用在基类上定义的Init抽象方法。
工厂模式具有可测试性优势,但不是您在此处使用它。第三种方法是让调用者传递一个工厂类的实例来使用(ImpliedRate方法将在工厂接口上)。这对于单元测试很方便,但对于API的消费者来说可能是繁重的。
答案 2 :(得分:1)
您可以使用常规方法以及修改过的Clone / Prototype模式等替代静态方法。例如:
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);
}
// ...
}
答案 3 :(得分:1)
根据我的经验,你只能实例化一个参数而不是泛型的构造函数。
你想要实现的目标只能通过反思来实现。
答案 4 :(得分:1)
尝试将静态(工厂)方法与继承混合时,您总是会遇到冲突。很难获得您正在寻找的多态行为。我有类似的问题,目前正在使用反射。如前所述,另一个选择是不使用静态方法(如果不需要)。然后,您可以使用模板方法或任何其他适用于继承的策略。
答案 5 :(得分:0)
任何理由不仅仅在通用基础上声明的非泛型接口上定义那些,然后对T进行转换?我没有看到任何通用的args被传递......