Я хочу скопировать значения от одного объекта до другого объекта. Что-то подобное для передачи значением, но с присвоением.
Например:
PushPin newValPushPin = oldPushPin; //I want to break the reference here.
Мне сказали записать конструктору копии для этого. Но этот класс имеет много свойств, вероятно, потребуется час, чтобы записать конструктору копии вручную.
Примечание: ICloneable не доступен в Silverlight.
Если вы можете пометить объект, который должен быть клонирован, как сериализуемый, вы можете использовать сериализацию в памяти для создания копии. Проверьте следующий код, он имеет то преимущество, что он будет работать и с другими типами объектов, и вам не нужно изменять конструктор копирования или копировать код каждый раз, когда свойство добавляется, удаляется или изменяется:
class Program
{
static void Main(string[] args)
{
var foo = new Foo(10, "test", new Bar("Detail 1"), new Bar("Detail 2"));
var clonedFoo = foo.Clone();
Console.WriteLine("Id {0} Bar count {1}", clonedFoo.Id, clonedFoo.Bars.Count());
}
}
public static class ClonerExtensions
{
public static TObject Clone<TObject>(this TObject toClone)
{
var formatter = new BinaryFormatter();
using (var memoryStream = new MemoryStream())
{
formatter.Serialize(memoryStream, toClone);
memoryStream.Position = 0;
return (TObject) formatter.Deserialize(memoryStream);
}
}
}
[Serializable]
public class Foo
{
public int Id { get; private set; }
public string Name { get; private set; }
public IEnumerable<Bar> Bars { get; private set; }
public Foo(int id, string name, params Bar[] bars)
{
Id = id;
Name = name;
Bars = bars;
}
}
[Serializable]
public class Bar
{
public string Detail { get; private set; }
public Bar(string detail)
{
Detail = detail;
}
}
C # не имеет конструктора копирования . Есть разные способы справиться с этим. На уровне ООП вы можете использовать наследование или агрегацию. AutoMapper тоже стоит попробовать.
Если вы хотите копировать при назначении, вы должны использовать структуру
вместо класса
. Но будьте осторожны, легко сделать небольшие ошибки. Настоятельно рекомендуется, чтобы все элементы были неизменяемыми, чтобы уменьшить вероятность ошибки.
Хотя это может не ответить на ваш вопрос напрямую, а добавить цент; обычно термин Clone
связан с неглубокой копией (объекты, на которые ссылаются). Чтобы иметь глубокую копию, я полагаю, вам нужно будет изучить некоторый шаблон создания (prototype?). Ответ на этот вопрос может помочь.
Вы реализуете метод клонирования объектов Джастина Ангела в Silverlight
с помощью System;
с помощью System. Отражение;
с использованием пространства имен System.Windows;
JustinAngelNet.Silverlight.Framework
{
public static class SilverlightExtensions
{
public static T Clone<T>(T source)
{
T cloned = (T) Activator.CreateInstance(source.GetType());
foreach (PropertyInfo curPropInfo in source.GetType().GetProperties())
{
if (curPropInfo.GetGetMethod() != null
&& (curPropInfo.GetSetMethod() != null))
{
// Handle Non-indexer properties
if (curPropInfo.Name != "Item")
{
// get property from source
object getValue = curPropInfo.GetGetMethod().Invoke(source, new object[] {});
// clone if needed
if (getValue != null && getValue is DependencyObject)
getValue = Clone((DependencyObject) getValue);
// set property on cloned
if (getValue != null)
curPropInfo.GetSetMethod().Invoke(cloned, new object[] {getValue});
}
// handle indexer
else
{
// get count for indexer
int numberofItemInColleciton =
(int)
curPropInfo.ReflectedType.GetProperty("Count").GetGetMethod().Invoke(source, new object[] {});
// run on indexer
for (int i = 0; i < numberofItemInColleciton; i++)
{
// get item through Indexer
object getValue = curPropInfo.GetGetMethod().Invoke(source, new object[] {i});
// clone if needed
if (getValue != null && getValue is DependencyObject)
getValue = Clone((DependencyObject) getValue);
// add item to collection
curPropInfo.ReflectedType.GetMethod("Add").Invoke(cloned, new object[] {getValue});
}
}
}
}
return cloned;
}
}
}
Затем вы можете сделать это
MyClass newObject = SilverlightExtensions.Clone (oldObject);
Единственный способ (о котором я знаю) сделать это и сделать это правильно - это реализовать копию самостоятельно. Возьмем, к примеру:
public class FrobAndState
{
public Frob Frobber { get; set;}
public bool State { get; set; }
}
public class Frob
{
public List<int> Values { get; private set; }
public Frob(int[] values)
{
Values = new List<int>(values);
}
}
В этом примере вам нужно знать , как был реализован Frob, то есть тот факт, что вам нужно вызвать конструктор для создания его копии, поскольку Values доступен только для чтения, чтобы иметь возможность сделать копию данного экземпляра FrobAndState.
Также - вы не могли просто реализовать FrobAndState.Copy таким образом:
public class FrobAndState
{
// ... Properties
public FrobAndState Copy()
{
var new = new FrobAndState();
new.State = this.State;
new.Frobber = this.Frobber;
}
}
Потому что и экземпляр FrobAndState, который вы вызвали .Copy (), и новый экземпляр, оба будут иметь ссылку на один и тот же экземпляр Frobber.
Короче говоря, копирование сложно , и любую реализацию Copy трудно сделать правильно.
Я хочу скопировать значения из одного объекта в другой объект. Нечто похожее на для передачи по значению, но с присваиванием.
Что вы подразумеваете под «с переуступкой»? Если вы имеете в виду, что хотите, чтобы люди могли сказать:
a = b;
И чтобы вы могли определить, что означает =
, единственный способ сделать это в C # - это если b
будет тип, отличный от a
, и вы определили неявное преобразование (или, что более тонко, если a
означает что-то вроде xY
, где Y
- свойство с сеттером). Вы не можете переопределить =
для простого назначения между идентичными типами в C #.
Мне сказали написать для этого конструктор копирования . Но у этого класса много свойств , вероятно, потребуется час, чтобы написать конструктор копирования вручную .
Если это действительно правда, то, думаю, у вас другая проблема. Ваш класс слишком велик.
Если вы сделаете свой класс Serializable
, вы сможете Serialize
его в MemoryStream
и Deserialize
в новый экземпляр.
Есть защищенный член под названием «MemberwiseClone», вы можете написать это в своем классе...
public MyClass Clone(){
return (MyClass)this.MemberwiseClone();
}
, тогда вы можете получить доступ..
MyClass newObject = oldObject.Clone();