問題:我有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