9

假设我有两个具有相同接口的类:

interface ISomeInterface 
{
    int foo{get; set;}
    int bar{get; set;}
}

class SomeClass : ISomeInterface {}

class SomeOtherClass : ISomeInterface {}

假设我有一个代表 SomeClass 的 ISomeInterface 实例。有没有一种简单的方法可以将其复制到 SomeOtherClass 的新实例中,而无需手动复制每个成员?

更新: 为了记录,我没有尝试将 SomeClass 的实例转换为 SomeOtherClass 的实例。我想做的是这样的:

ISomeInterface sc = new SomeClass() as ISomeInterface;
SomeOtherClass soc = new SomeOtherClass();

soc.foo = sc.foo;
soc.bar = soc.bar;

我只是不想手动为每个对象做这些,因为这些对象有很多属性。

4

9 回答 9

9

您可以在每个类中创建隐式运算符来为您进行转换:

public class SomeClass
{
    public static implicit operator SomeOtherClass(SomeClass sc)
    {
        //replace with whatever conversion logic is necessary
        return new SomeOtherClass()
        {
            foo = sc.foo,
            bar = sc.bar
        }
    }

    public static implicit operator SomeClass(SomeOtherClass soc)
    {
        return new SomeClass()
        {
            foo = soc.foo,
            bar = soc.bar
        }
    }
    //rest of class here
}

然后SomeOtherClass soc = sc;反之亦然。

于 2008-11-19T22:27:59.053 回答
6

界面的意义不是不必这样做吗?您是否正在对 SomeOtherClass 的具体实现做些什么?不要使用具体的实现,而是使用接口,并且使用 SomeClass 或 SomeOther 类无关紧要。

除此之外,您能做的最好的事情是编写某种辅助函数(您仍然必须手动完成,或查看反射)复制接口上的每个属性,如下所示:

   public ISomeInterface CopyValues(ISomeInterface fromSomeClass, ISomeInterface toSomeOtherClass)
   {
    //copy properties here
    return toSomeOtherClass;
    }

但是,我的第一直觉是远离实现并专注于使用您的界面,那么下面的内容就无关紧要了。

于 2008-11-19T22:12:04.000 回答
4

Reflection ... 循环遍历每个属性,并将其设置在另一个对象的相应属性上。

于 2008-11-19T22:08:44.490 回答
4

查看乔对反射解决方案的回答。

我假设您使用的是 Visual Studio。

你熟悉 ctrl+shift+r 和 ctrl+shift+p 快捷键吗?如果没有, ctrl+shift+r 开始/结束录制击键宏。ctrl+shift+p 播放录制的宏。

当我设置了很多属性时,我所做的是将属性声明复制到我想要设置它们的位置并记录一个宏,用于将声明更改为 set 语句并将光标移动到下一行,然后我播放它直到我完成所有设置语句。

于 2008-11-19T23:31:37.397 回答
3

不,要透明地将对象从一种类型转换(转换)为另一种类型,您拥有的对象的底层具体类必须从您尝试将其转换为的类继承,即使它们都实现相同的接口。

想一想,所有两个对象都必须具有共同点才能实现相同的接口是方法签名的相同子集。它们甚至可能没有(可能没有)具有相同的属性或数据字段。

于 2008-11-19T22:10:19.760 回答
3

这不行吗?

class MyClass : ICloneable
{
public MyClass()
{

}
public object Clone() // ICloneable implementation
{
MyClass mc = this.MemberwiseClone() as MyClass;

return mc;
}

您只需调用:MyClass.Clone()。

于 2008-11-19T22:13:07.650 回答
3

“你能给我一个例子来说明我如何做到这一点(或者至少指出我要使用的正确方法)吗?我似乎无法在 MSDN 上找到它们”——Jason Baker

杰森,类似于以下内容:

var props = typeof(Foo)
            .GetProperties(BindingFlags.Public | BindingFlags.Instance);

foreach (PropertyInfo p in props)
{
     // p.Name gives name of property
}

我建议编写一个工具来吐出复制构造函数所需的代码,而不是在运行时进行反射 - 这会降低性能。

于 2008-11-19T23:10:41.917 回答
3
   ISomeInterface sc = new SomeClass() as ISomeInterface;
   SomeOtherClass soc = new SomeOtherClass();
   foreach (PropertyInfo info in typeof(ISomeInterface)
                                     .GetProperties(BindingFlags.Instance
                                                     |BindingFlags.Public))
   {
       info.SetValue(soc,info.GetValue(sc,null),null);
   }
于 2008-11-19T23:53:29.443 回答
2

我确实喜欢以下内容,并且使用隐式运算符将一个对象转换为另一个对象非常有效:

课堂节目
    {
        静态无效主要(字符串 [] 参数)
        {
            Console.WriteLine("你好");
            ExecutionReport er = new ExecutionReport("ORDID1234",3000.43,DateTime.UtcNow);
            订单 ord = new Order();
            顺序 = 呃;
            Console.WriteLine("传输的值是:" + er.OrderId + "\t" + ord.Amount.ToString() + "\t" + ord.TimeStamp.ToString() + "\t");
            Console.ReadLine();
        }
    }


    公共课秩序
    {
        公共字符串 OrderId { 获取;放; }
        公共双金额{获取;放; }
        公共日期时间时间戳{获取;放; }
        公共静态隐式运算符 ExecutionReport(Order ord)
        {
            返回新的执行报告()
            {
                OrderId = ord.OrderId,
                金额 = ord.Amount,
                时间戳 = ord.TimeStamp
            };
        }
        公共静态隐式运算符 Order(ExecutionReport er)
        {
            返回新订单()
            {
                OrderId = er.OrderId,
                金额=呃.金额,
                时间戳 = er.TimeStamp
            };
        }

        公共秩序()
        { }
    }

    公共类执行报告
    {
        公共字符串 OrderId { 获取;放; }
        公共双金额{获取;放; }
        公共日期时间时间戳{获取;放; }
        公共执行报告(){}
        public ExecutionReport(string orderId,double amount, DateTime ts)
        {
            订单编号 = 订单编号;金额=金额;时间戳 = ts;
        }
    }
于 2010-12-08T20:56:14.737 回答