2009-08-13 68 views
14

我一直在使用C#多年,但只是遇到了這個問題,這是困擾我,我真的不知道如何提出問題,所以,對於這個例子!c#中的接口屬性副本#

public interface IAddress 
{ 
    string Address1 { get; set; } 
    string Address2 { get; set; } 
    string City { get; set; } 
    ... 
} 

public class Home : IAddress 
{ 
    // IAddress members 
} 

public class Work : IAddress 
{ 
    // IAddress members 
} 

我的問題是,我想複製IAddress屬性的值從一個類到另一個。這是可能的,在一個簡單的單行聲明中,還是我還需要對每一個屬性進行屬性分配?我真的很驚訝這個看似簡單的東西讓我難以忍受,如果它不可能以簡明的方式存在,是否有人有任何捷徑來做這種事情?

謝謝!

+0

想到這可能是http://stackoverflow.com/questions/563253/c-generic-copy-constructor的重複。 如果沒有別的,它應該回答你的問題。 – 2009-08-13 16:01:05

回答

2

這裏沒有一行代碼。

如果你做了很多,你可以看看代碼生成的某種形式,也許使用T4模板和反射。

順便說一句COBOL對此有一個聲明:移動相應的家庭工作。

12

你可以建立一個擴展方法:

public static void CopyAddress(this IAddress source, IAddress destination) 
{ 
    if (source is null) throw new ArgumentNullException("source"); 
    if (destination is null) throw new ArgumentNullException("destination"); 

    //copy members: 
    destination.Address1 = source.Address1; 
    //... 
} 
+0

我真的很喜歡這個解決方案。謝謝! – opedog 2009-08-13 16:04:22

+2

請參閱下面的響應,其中有一個通用的擴展方法,當接口更改或set/get方法被添加/刪除時,這些擴展方法並不脆弱。 – plinth 2009-08-13 16:21:21

1

您將需要創建要做到這一點

public void CopyFrom(IAddress source) 
{ 
    this.Address1 = source.Address1; 
    this.Address2 = source.Address2; 
    this.City = source.city; 
} 
+0

這是一種脆弱的方法,如果添加新屬性可能會中斷。 – plinth 2009-08-13 16:16:46

+0

是的,大多數方式,除非你使用反射。做用戶談論這個是一個有效的選擇。 – 2009-08-13 18:06:52

0

的方法你可以對每類取一個IAddress一個構造函數和具有執行會員在內部填充。

public WorkAddress(Iaddress address) 
{ 
    Line1 = IAddress.Line1; 
    ... 
} 

可維護性使用反射來獲取屬性名稱。

HTH,

0

如果封裝的家庭和工作地址的公用部分成一個單獨的類可以讓您的生活更輕鬆。然後,您可以簡單地複製該屬性。這對我來說似乎是更好的設計。

或者,您可以將反射和屬性的解決方案一起破解,其中一個對象中的屬性值被複制到另一個對象中的匹配(和標記)屬性。當然,這不會是一種單線解決方案,但如果您擁有大量的屬性,它可能會比其他解決方案更快,更易於維護。

2

我不相信這裏有一個語言準備好的解決方案(所有的屬性都需要有getter和setter)。

您可以使用Copy(Address add)方法創建Address作爲抽象類。

另外,您可以使家庭和工作有一個IAddress,而不是擴展一個。該副本將立即生效。

4

Jimmy Bogard的AutoMapper對於那種映射操作非常有用。

+0

Apache Commons有一個名爲「BeanUtils」的庫,當我用Java開發時,它曾經用過。 Martinho Fernandes所建議的似乎是最接近的相應的.net庫。 – 2009-08-13 16:08:57

18

下面是做這件事有沒有關係接口:

public static class ExtensionMethods 
{ 
    public static void CopyPropertiesTo<T>(this T source, T dest) 
    { 
     var plist = from prop in typeof(T).GetProperties() where prop.CanRead && prop.CanWrite select prop; 

     foreach (PropertyInfo prop in plist) 
     { 
      prop.SetValue(dest, prop.GetValue(source, null), null); 
     } 
    } 
} 

class Foo 
{ 
    public int Age { get; set; } 
    public float Weight { get; set; } 
    public string Name { get; set; } 
    public override string ToString() 
    { 
     return string.Format("Name {0}, Age {1}, Weight {2}", Name, Age, Weight); 
    } 
} 

static void Main(string[] args) 
{ 
    Foo a = new Foo(); 
    a.Age = 10; 
    a.Weight = 20.3f; 
    a.Name = "Ralph"; 
    Foo b = new Foo(); 
    a.CopyPropertiesTo<Foo>(b); 
    Console.WriteLine(b); 
} 

在你的情況,如果你只想要一組接口性能的複製,你可以這樣做:

((IAddress)home).CopyPropertiesTo<IAddress>(b); 
+1

你應該在那裏貼一個約束 - 這裏T:IAddress。然後,您還可以緩存反射查找,而不是每次調用都執行此操作,並且仍然可以避免在界面更改時更新方法。 – 2009-08-13 16:28:53

+0

順便說一句,我知道你正在嘗試更普遍的情況,但在這種情況下,它似乎試圖用大錘擊釘。 – 2009-08-13 16:29:25

+1

如果'source'和'dest'是不同的類型,你的代碼將在運行時中斷,這是他們原來的問題。你可以通過從'T'而不是'source'獲取屬性列表來修復它。例如:'var plist = from typeof(T).GetProperties()其中prop.CanRead && prop.CanWrite選擇prop;' – LukeH 2009-08-13 17:14:49