问题:我有2种类型的是结果集的2个不同的程序DB: Proc1Result,Proc2Result(我们不得不分开他们 - 但它们基本上是相同自带输入/输出)明确投基类派生类
然后我决定,我可以利用在运行时需要的程序之间切换的界面 - 但这只是意味着我需要1种常见的类型,而我可以转换Proc1Result和Proc2Result
所以我不需要维护这个新类(创建所有的属性,添加/删除,如果一个在DB结果nything变化) - 我得到的这个类从结果之一:
public class DerivedClassForInterface : Proc1Result {}
然后我实现了从第二PROC工作正常明确的转换,但是当我要实现从基类显式的推导类 - 它不会允许我(因为它已经有点“不” - 但它在运行时失败):
public class DerivedClassForInterface : Proc1Result
{
//ok - and works as expected
public static explicit operator DerivedClassForInterface(Proc2Result v)
{
return new DerivedClassForInterface
{
...
};
}
//fail: 'user-defined' conversations to or from a base class are not allowed
public static explicit operator DerivedClassForInterface(Proc1Result v)
{
return new DerivedClassForInterface
{
...
};
}
}
所以此工程:
//result2 is of type Proc1Result
DerivedClassForInterface castedResult = (DerivedClassForInterface)result2;
//compiles - works as expected at runtime
但这并不:
//result1 is of type Proc1Result
DerivedClassForInterface castedResult = (DerivedClassForInterface)result1;
//compiles - conversation fails at runtime
那么,为什么我不能写自己的显式操作符,如果你不能从基类转换为派生类?
有趣的是,编译器允许我从基类转换为派生类,但它在运行时不起作用。
也许我会去为简单的功能,这将为我“铸造”。任何人都可以提出一个更好的解决方案(记住,我想保持“DerivedClassForInterface”服从于“Proc1Result”改变(或“Proc2Result” - 无所谓))
编辑
@Peter Duniho - 这里的类型“Proc1Result”和“Proc2Result”是作为存储过程(linq2sql)的结果生成的。我希望有一个代码,当那些过程的输出发生变化时,我不需要触及代码(因为我们需要分割一大堆过程 - 并且实现新模块可以并且通常会增加更多输出)。
Proc1和Proc2基本上是相同的存储过程(它们需要完全相同的输入并提供相同的输出(按类型而非数据方式))。他们都与不同的数据段一起工作,并且需要分开。
对不起,让这个混乱的(在我的工作一天结束...),而不是澄清 - 这里的问题居然是:
为什么编译器让我从基础转换为派生类中运行时会导致异常?为什么我不能自己实现这个工作(...因为它已经有了 - 但它在运行时不起作用?)
从我的立场所以 - 它看起来如下:
- 我不能因为它已经存在
实现这个转换 - 然而,这注定是行不通
这里是“最小的,完整的和可验证的代码示例”(感谢链接):
//results from stored procedures in database which got splitted appart (linq 2 sql)
class Proc1Result { }
class Proc2Result { }
//
class DerivedClassForInterface : Proc1Result
{
public static explicit operator DerivedClassForInterface(Proc2Result v)
{
//this part would be exported in generic function
var derivedClassInstance = new DerivedClassForInterface();
var properties = v.GetType().GetProperties();
foreach (var property in properties)
{
var propToSet = derivedClassInstance.GetType().GetProperty(property.Name);
if (propToSet.SetMethod != null) propToSet.SetValue(derivedClassInstance, property.GetValue(v));
}
return derivedClassInstance;
}
}
interface IProcLauncher
{
DerivedClassForInterface GetNeededData();
}
class ProcLauncher1 : IProcLauncher
{
public DerivedClassForInterface GetNeededData()
{
var dataFromDb = new Proc1Result();/*just ilustrative*/
return (DerivedClassForInterface)dataFromDb;
}
}
class ProcLauncher2 : IProcLauncher
{
public DerivedClassForInterface GetNeededData()
{
var dataFromDb = new Proc2Result();/*just ilustrative*/
return (DerivedClassForInterface)dataFromDb;
}
}
class Program
{
static void Main(string[] args)
{
bool causeInvalidCastException = true;
IProcLauncher procedureLauncher;
if (causeInvalidCastException) procedureLauncher = new ProcLauncher1();
else procedureLauncher = new ProcLauncher2();
var result = procedureLauncher.GetNeededData();
Console.WriteLine("I got here!");
}
}
当时的想法是:
- 无需更改任何代码,如果程序改变输出。
- 在运行时决定使用哪个proc。
- 将转换部分导出为通用功能。
- 被注射。
我可以解决这个问题 - 比如说 - 只需要一个泛型函数来处理所有情况下的对话,但问题以粗体显示。
'Proc2Result'定义在哪里?我只看到'Proc1Result'。 –
我对你的问题有点遗憾,但是如果我正确理解你的问题,那你为什么不把Proc1Result和Proc2Result之间的所有公共领域复制到一个通用接口。你能告诉你哪些类可以修改,哪些不能。你也可以用一些代码来演示你的问题(不是带有演员操作符的解决方案) – Vikhram
@ rory.ap - Proc1Result和Proc2Result是由存储过程产生的Link2Sql分类生成的。最初的要求是将他们在两个不同的过程中进行分割(不在1个过程中)。最初我想通过强制转换(出于某种原因,编译器允许我将基类的实例obj转换为派生 - 但在运行时失败)。 我可以在2,3 ..等更多的方式解决问题 - 但我想知道为什么编译器让我这样做 - 但运行时没有。 – RUKAclMortality