2009-02-19 131 views
6

我現在有這種類型的代碼:C#:鑄造類型的動態

private void FillObject(Object MainObject, Foo Arg1, Bar Arg2) 
{ 
    if (MainObject is SomeClassType1) 
    { 
     SomeClassType1 HelpObject = (SomeClassType1)MainObject; 
     HelpObject.Property1 = Arg1; 
     HelpObject.Property2 = Arg2; 
    } 
    else if (MainObject is SomeClassType2) 
    { 
     SomeClassType2 HelpObject = (SomeClassType2)MainObject; 
     HelpObject.Property1 = Arg1; 
     HelpObject.Property2 = Arg2; 
    } 
} 

假設SomeClassType1和SomeClassType2具有相同的組,我要分配(儘管它們可能在其他的不同)的特性,是有可能動態地將MainObject轉換爲適當的類型,然後賦值,而不重複代碼? 這是我想看看到底是什麼:

private void FillObject(Object MainObject, Foo Arg1, Bar Arg2) 
{ 
    Type DynamicType = null; 

    if (MainObject is SomeClassType1) 
    { 
     DynamicType = typeof(SomeClassType1); 
    } 
    else if (MainObject is SomeClassType2) 
    { 
     DynamicType = typeof(SomeClassType2); 
    } 

    DynamicType HelpObject = (DynamicType)MainObject; 
    HelpObject.Property1 = Arg1; 
    HelpObject.Property2 = Arg2; 
} 

很顯然C#抱怨不能夠找到DynamicType:

類型或命名空間名稱「DynamicType」找不到(您是否缺少使用指令或程序集引用?)

在C#2.0中可能會這樣嗎?如果它比我現在的代碼更混亂,比我認爲這樣做沒有意義,但我很有興趣瞭解。謝謝!

編輯:只是爲了澄清,我完全理解,實現一個接口是最合適的,可能是正確的解決方案。也就是說,我更感興趣的是如何在沒有實現接口的情況下做到這一點。感謝您的好評!

回答

15

它看起來像你關心的兩種類型實現相同的兩個屬性。在這種情況下,你想要做的就是定義一個接口這些屬性:

public interface IMyInterface 
{ 
    public Foo Property1 {get; set;} 
    public Bar Property2 {get;set;} 
} 

然後,確保每個類的告訴他們實現新的界面編譯器。最後,使用一個通用的方法與被約束到interace類型參數:

private void FillObject<T>(T MainObject, Foo Arg1, Bar Arg2) 
    where T : IMyInterface 
{ 
    MainObject.Property1 = Arg1; 
    MainObject.Property2 = Arg2; 
} 

注意,即使有額外的代碼申報的接口,這些片段最終仍小於或者您發佈的片段之一在問題中,如果您關心的類型數量增加,則此代碼更容易擴展。

9

基本上你在這裏做的是根據對象的類型寫一個switch語句。除了你的第一個例子(這在最好的情況下是單調乏味的),沒有什麼內在的好方法可以做到這一點。

我寫了一個小型框架來切換類型,使語法更簡潔一些。它允許你編寫如下代碼。

TypeSwitch.Do(
    sender, 
    TypeSwitch.Case<Button>(
     () => textBox1.Text = "Hit a Button"), 
    TypeSwitch.Case<CheckBox>(
     x => textBox1.Text = "Checkbox is " + x.Checked), 
    TypeSwitch.Default(
     () => textBox1.Text = "Not sure what is hovered over")); 

博客文章:http://blogs.msdn.com/jaredpar/archive/2008/05/16/switching-on-types.aspx

2

,而不是試圖投,或許你可以嘗試設置使用反射性能。

4
private void FillObject(Object MainObject, Foo Arg1, Bar Arg2) 
{ 
    Type t = MainObject.GetType(); 

    t.GetProperty("Property1").SetValue(MainObject, Arg1, null); 
    t.GetProperty("Property2").SetValue(MainObject, Arg2, null); 
} 
+0

我認爲這裏的泛型更合適,但至少我會檢查以確保屬性存在第一。 – 2009-02-19 18:25:47

+0

我只是想展示你用反射的方式。對於這個問題,這不是*完整*或*推薦*方法。 – 2009-02-19 18:28:04

+0

我覺得這個災難已經寫滿了...... – 2009-02-19 18:29:45

7

你能修改SomeClassType1,SomeClassType2等嗎?如果是,那麼我會建議你創建一個包含你的公共屬性的接口,然後在FillObject()內對該接口進行類型轉換來設置屬性。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace SO566510 
{ 
    interface IMyProperties 
    { 
     int Property1 { get; set; } 
     int Property2 { get; set; } 
    } 

    class SomeClassType1 : IMyProperties 
    { 
     public int Property1 { get; set; } 
     public int Property2 { get; set; } 
    } 

    class SomeClassType2 : IMyProperties 
    { 
     public int Property1 { get; set; } 
     public int Property2 { get; set; } 
    } 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var obj1 = new SomeClassType1(); 
      var obj2 = new SomeClassType2(); 

      FillObject(obj1, 10, 20); 
      FillObject(obj2, 30, 40); 

     } 

     private static void FillObject(IMyProperties objWithMyProperties 
            , int arg1, int arg2) 
     { 
      objWithMyProperties.Property1 = arg1; 
      objWithMyProperties.Property2 = arg2; 
     } 
    } 
} 
3

一些想法:

  1. 有兩種類型的從具有公共屬性的相同類型繼承
  2. 有兩種實現一個具有公共屬性
  3. 使用反射來設置屬性相同的接口而不是直接設置它們(這可能比它的價值更難看)
  4. 使用新的dynamic feature,我沒有試過這個,但看起來像它可能會解決您的問題
0

我在ASP.NET MVC應用程序中使用反射動態地轉換對象。基本上我枚舉類的屬性,在數據存儲中找到相應的值並動態地轉換該值並將其分配給對象實例。看我的博客文章 Dynamic Casting with .NET