C# 使用接口将对象从一种类型转换为另一种类型?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/303555/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using an interface to convert an object from one type to another?
提问by Jason Baker
Suppose I have two classes with the same interface:
假设我有两个具有相同接口的类:
interface ISomeInterface
{
int foo{get; set;}
int bar{get; set;}
}
class SomeClass : ISomeInterface {}
class SomeOtherClass : ISomeInterface {}
Suppose I have an instance of ISomeInterface that represents a SomeClass. Is there an easy way to copy that into a new instance of SomeOtherClass without copying each member by hand?
假设我有一个代表 SomeClass 的 ISomeInterface 实例。有没有一种简单的方法可以将其复制到 SomeOtherClass 的新实例中,而无需手动复制每个成员?
UPDATE:For the record, I'm nottrying to cast the instance of SomeClass into the instance of SomeOtherClass. What I'd like to do is something like this:
更新:为了记录,我不是试图将 SomeClass 的实例转换为 SomeOtherClass 的实例。我想做的是这样的:
ISomeInterface sc = new SomeClass() as ISomeInterface;
SomeOtherClass soc = new SomeOtherClass();
soc.foo = sc.foo;
soc.bar = soc.bar;
I just don't want to have to do that for each by hand as these objects have lots of properties.
我只是不想手动为每个对象执行此操作,因为这些对象具有很多属性。
采纳答案by Winston Smith
"Would you be able to give me an example of how I can do that (or at least point me towards the right methods to be using)? I don't seem to be able to find them on MSDN" – Jason Baker
“你能给我一个例子来说明我如何做到这一点(或者至少指出我要使用的正确方法)?我似乎无法在 MSDN 上找到它们” – Jason Baker
Jason, something like the following:
杰森,类似于以下内容:
var props = typeof(Foo)
.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (PropertyInfo p in props)
{
// p.Name gives name of property
}
I'd suggest writing a tool to spit out the code you need for a copy constructor, as opposed to doing it reflectively at runtime - which would be less performant.
我建议编写一个工具来吐出复制构造函数所需的代码,而不是在运行时反射性地执行它 - 这会降低性能。
回答by Joel Martinez
Reflection ... loop through every property, and set it on the corresponding property on the other object.
反射 ... 遍历每个属性,并将其设置在另一个对象的相应属性上。
回答by Charles Bretana
No, to transparently convert (cast) an object from one type to another, the underlying concrete class of the object you have, must inherit from the class the you are trying to cast it to, even if they both inplement the same interface.
不,要将对象从一种类型透明地转换(转换)到另一种类型,您拥有的对象的底层具体类必须从您尝试将其转换为的类继承,即使它们都实现了相同的接口。
Think about it, all two objects have to have in common to implement the same interface is the same subset of method signatures. They might not (probably do not) even have the same properties or data fields.
想想看,所有两个对象都必须有共同点才能实现相同的接口,即方法签名的相同子集。它们甚至可能不(可能不)具有相同的属性或数据字段。
回答by mendicant
Isn't the point of an interface to not have to do that? Are you doing something with the concrete implementation of SomeOtherClass? Instead of using the concrete implementation, use the interface and it shouldn't matter if you use SomeClass or SomeOther class.
接口的意义不是不必这样做吗?你在用 SomeOtherClass 的具体实现做些什么吗?使用接口而不是使用具体实现,使用 SomeClass 或 SomeOther 类应该无关紧要。
Other than that, the best you could do is to write some sort of a helper function (you'd still have to do it manually, or look into reflection) that copies each Property on the Interface that would look like this:
除此之外,您能做的最好的事情是编写某种辅助函数(您仍然必须手动执行此操作,或查看反射)来复制接口上的每个属性,如下所示:
public ISomeInterface CopyValues(ISomeInterface fromSomeClass, ISomeInterface toSomeOtherClass)
{
//copy properties here
return toSomeOtherClass;
}
However, my first instinct would be to say stay away from the implementation and concentrate using your interface instead, then it won't matter what's lying underneath.
但是,我的第一直觉是远离实现并专注于使用您的界面,那么下面的内容就无关紧要了。
回答by netadictos
wouldn't this work?
这行不通?
class MyClass : ICloneable
{
public MyClass()
{
}
public object Clone() // ICloneable implementation
{
MyClass mc = this.MemberwiseClone() as MyClass;
return mc;
}
You only have to call: MyClass.Clone().
你只需要调用:MyClass.Clone()。
回答by Adam Lassek
You can create implicit operators in each class to do the conversion for you:
您可以在每个类中创建隐式运算符来为您进行转换:
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
}
and then SomeOtherClass soc = sc;
and vice versa would work.
然后SomeOtherClass soc = sc;
反之亦然。
回答by CrashCodes
Check out Joe's answer for the Reflection solution.
查看 Joe 对反射解决方案的回答。
I assume you are using Visual Studio.
我假设您使用的是 Visual Studio。
Are you familiar with the ctrl+shift+r and ctrl+shift+p shortcuts? If not, ctrl+shift+r begins/ends recording a keystroke macro. ctrl+shift+p plays the recorded macro.
你熟悉 ctrl+shift+r 和 ctrl+shift+p 快捷键吗?如果没有,ctrl+shift+r 开始/结束记录击键宏。ctrl+shift+p 播放录制的宏。
What I've done when I have set a lot of properties is to copy the property declarations to where I want them to be set and record a macro for mutating the declaration to a set statement and moving the cursor to the next line, then I just play it until I have all the set statements done.
当我设置了很多属性时,我所做的是将属性声明复制到我希望设置它们的位置,并记录一个宏以将声明更改为 set 语句并将光标移动到下一行,然后我播放它直到我完成所有设置的语句。
回答by tvanfosson
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);
}
回答by Pankaj Awasthi
I did like the following and it works just very well to convert from one object into another using implicit operator:
我确实喜欢以下内容,并且使用隐式运算符将一个对象转换为另一个对象非常有效:
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; } }