我正在尝试做类似以下的事情-
public abstract class Utility<A, B>
{
// Return values cannot be cached in class-scoped fields as these need to be invoked by threaded application
public abstract A GetPrimaryData(float foo);
public abstract B GetSecondaryData(float bar, A primaryData);
public abstract float ProcessData(A primaryData, B secondaryData);
}
public class SpecificUtility : Utility<C, D>
{
public override C GetPrimaryData(float foo) { /* implementation */ }
public override D GetSecondaryData(float bar, C primaryData) { /* implementation */ }
public override float ProcessData(C primaryData, D secondaryData) { /* implementation */ }
}
public class UserClass
{
// Important - this script doesn't care what A or B is! Should be able to use ANY implementation of Utility.
// As a result, we can't define UserClass as a generic of <A, B>
public Utility<A, B> Utility;
public void UseCase()
{
A utilPrimaryData = Utility.GetPrimaryData(GetFoo());
B utilSecondaryData = Utility.GetSecondaryData(GetBar(), utilPrimaryData);
float dataUserActuallyCaresAbout = Utility.ProcessData(utilPrimaryData, utilSecondaryData);
}
}
我正在考虑制作一个
IUtility
类实现的 Utility
接口,并且 UserClass
与之交互,但这实际上并不能解决问题,因为 UserClass
需要实际获取 PrimaryData
和 SecondaryData
然后 Utility
将处理成用户需要使用的值。
我能想到的唯一解决方案是让
GetPrimaryData
和 GetSecondaryData
返回通用对象,然后将其转换为 Utility
子类期望的特定类型,但我发现这非常不令人满意并怀疑性能影响也不会很大。
您可以使用
dynamic
:
public void UseCase()
{
var util = (dynamic)Utility;
dynamic utilPrimaryData = util.GetPrimaryData(GetFoo());
dynamic utilSecondaryData = util.GetSecondaryData(GetBar(), utilPrimaryData);
float dataUserActuallyCaresAbout = util.ProcessData(utilPrimaryData, utilSecondaryData);
Console.WriteLine(dataUserActuallyCaresAbout);
}
请注意,您将失去这些调用的所有类型安全性,将方法名称等的任何错误转变为运行时错误。