Использование интерфейса для преобразования объекта из одного типа в другой?
Вопрос
Предположим, у меня есть два класса с одинаковым интерфейсом:
interface ISomeInterface
{
int foo{get; set;}
int bar{get; set;}
}
class SomeClass : ISomeInterface {}
class SomeOtherClass : ISomeInterface {}
Предположим, у меня есть экземпляр ISomeInterface, который представляет SomeClass. Есть ли простой способ скопировать это в новый экземпляр SomeOtherClass, не копируя каждый член вручную?
ОБНОВЛЕНИЕ . Для записи, я не пытаюсь привести экземпляр SomeClass в экземпляр SomeOtherClass. Я хотел бы сделать что-то вроде этого:
ISomeInterface sc = new SomeClass() as ISomeInterface;
SomeOtherClass soc = new SomeOtherClass();
soc.foo = sc.foo;
soc.bar = soc.bar;
Я просто не хочу делать это для каждого вручную, так как эти объекты имеют много свойств.
Решение
" Не могли бы вы привести пример того, как я могу это сделать (или, по крайней мере, указать мне, какие методы следует использовать)? Кажется, я не могу найти их в MSDN " & # 8211; Джейсон Бейкер
Джейсон, что-то вроде следующего:
var props = typeof(Foo)
.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (PropertyInfo p in props)
{
// p.Name gives name of property
}
Я бы предложил написать инструмент для выделения кода, необходимого для конструктора копирования, в отличие от рефлективного выполнения во время выполнения - который был бы менее производительным.
Другие советы
Вы можете создавать неявные операторы в каждом классе, чтобы выполнить преобразование для вас:
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;
и наоборот.
Разве интерфейс не должен делать это? Вы что-то делаете с конкретной реализацией SomeOtherClass? Вместо использования конкретной реализации используйте интерфейс, и не должно иметь значения, используете ли вы класс SomeClass или SomeOther.
Кроме того, лучшее, что вы можете сделать, это написать какую-нибудь вспомогательную функцию (вам все равно придется делать это вручную или смотреть в отражение), которая копирует каждое свойство интерфейса, которое будет выглядеть следующим образом: р>
public ISomeInterface CopyValues(ISomeInterface fromSomeClass, ISomeInterface toSomeOtherClass)
{
//copy properties here
return toSomeOtherClass;
}
Тем не менее, мой первый инстинкт был бы заключаться в том, чтобы держаться подальше от реализации и сконцентрироваться на использовании своего интерфейса, тогда не будет иметь значения, что находится под ним.
Reflection ... перебирает каждое свойство и устанавливает его в соответствующем свойстве другого объекта.
Проверьте ответ Джо для решения Reflection.
Я предполагаю, что вы используете Visual Studio. Р>
Вам знакомы сочетания клавиш ctrl + shift + r и ctrl + shift + p? Если нет, Ctrl + Shift + R начинает / заканчивает запись макроса нажатия клавиш. Ctrl + Shift + P воспроизводит записанный макрос. Р>
Что я сделал, когда установил много свойств, так это скопировал объявления свойств туда, где я хочу, чтобы они были установлены, и записал макрос для преобразования объявления в оператор set и перемещения курсора на следующую строку. затем я просто играю, пока не выполню все установленные операторы.
Нет, для прозрачного преобразования (приведения) объекта из одного типа в другой, базовый конкретный класс объекта, который у вас есть, должен наследовать от класса, к которому вы пытаетесь его привести, даже если они оба дополняют одно и то же. интерфейс. р>
Подумайте, все два объекта должны иметь общее для реализации одного и того же подмножества сигнатур методов. Они могут не иметь (вероятно, не иметь) даже одинаковых свойств или полей данных. Р>
это не сработает?
class MyClass : ICloneable
{
public MyClass()
{
}
public object Clone() // ICloneable implementation
{
MyClass mc = this.MemberwiseClone() as MyClass;
return mc;
}
Вам нужно только позвонить: MyClass.Clone (). Р>
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);
}
Мне понравилось следующее, и он очень хорошо работает для преобразования из одного объекта в другой, используя неявный оператор:
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; } }