使用接口将对象从一种类型转换为另一种类型?

时间:2008-11-19 22:05:53

标签: c# .net .net-3.5 interface copying

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

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

class SomeClass : ISomeInterface {}

class SomeOtherClass : ISomeInterface {}

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

UPDATE:对于记录,我尝试将SomeClass的实例强制转换为SomeOtherClass的实例。我想做的是这样的事情:

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

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

我只是不想为每个人手动执行此操作,因为这些对象具有许多属性。

9 个答案:

答案 0 :(得分: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;反之亦然。

答案 1 :(得分:6)

接口的重点不是必须这样做吗?您是否正在使用SomeOtherClass的具体实现?使用界面而不是使用具体实现,如果您使用SomeClass或SomeOther类则无关紧要。

除此之外,您可以做的最好的事情是编写某种辅助函数(您仍需要手动执行,或查看反射),复制接口上的每个属性,如下所示:

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

然而,我的第一直觉是说要远离实施并使用你的界面集中精力,那么下面的内容并不重要。

答案 2 :(得分:4)

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

答案 3 :(得分:4)

查看Joe对Reflection解决方案的回答。

我假设您使用的是Visual Studio。

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

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

答案 4 :(得分:3)

不,为了将对象从一种类型透明地转换(强制转换)到另一种类型,您拥有的对象的基础具体类必须从您尝试将其强制转换为的类继承,即使它们都是相同的接口

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

答案 5 :(得分:3)

这不会起作用吗?

class MyClass : ICloneable
{
public MyClass()
{

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

return mc;
}

你只需要调用:MyClass.Clone()。

答案 6 :(得分:3)

“你能给我一个如何做到这一点的例子(或者至少指出我正确使用的方法)吗?我似乎无法在MSDN上找到它们” - 杰森贝克

杰森,如下所示:

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

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

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

答案 7 :(得分: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);
   }

答案 8 :(得分:2)

我确实喜欢以下内容,它非常适合使用隐式运算符从一个对象转换为另一个对象:

class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("hello");
            ExecutionReport er = new ExecutionReport("ORDID1234",3000.43,DateTime.UtcNow);
            Order ord = new Order();
            ord = er;
            Console.WriteLine("Transferred values are : " + er.OrderId + "\t" + ord.Amount.ToString() + "\t" + ord.TimeStamp.ToString() + "\t");
            Console.ReadLine();
        }
    }


    public  class Order
    {
        public string OrderId { get; set; }
        public double Amount { get; set; }
        public DateTime TimeStamp { get; set; }
        public static implicit operator ExecutionReport(Order ord)
        {
            return new ExecutionReport()
            {
                OrderId = ord.OrderId,
                Amount = ord.Amount,
                TimeStamp = ord.TimeStamp
            };
        }
        public static implicit operator Order(ExecutionReport er)
        {
            return new Order()
            {
                OrderId = er.OrderId,
                Amount = er.Amount,
                TimeStamp = er.TimeStamp
            };
        }

        public Order()
        { }
    }

    public  class ExecutionReport
    {
        public string OrderId { get; set; }
        public double Amount { get; set; }
        public DateTime TimeStamp { get; set; }
        public ExecutionReport() { }
        public ExecutionReport(string orderId,double amount, DateTime ts)
        {
            OrderId = orderId; Amount = amount; TimeStamp = ts;
        }
    }