Это сообщение в блоге имеет некоторую информацию о том, как команда Visual Studio делает их продукт доступным:
Рабочая группа Visual Studio Туристическое Действие Accessibility Lab
Многие программисты используют Emacspeak:
Rex - мы реализовали нечто очень похожее в большом корпоративном веб-продукте, и в итоге мы явно создали интерфейс IDeepCloneable, который реализовали многие из наших объектов. Интересно то, что мы поддержали его с помощью BinarySerializer просто потому, что это удобный и практически надежный способ сделать глубокую копию объекта без всех хлопот по отражению или принуждению разработчиков писать и тестировать методы клонирования.
Это работает как Шарм. Наша команда несколько раз останавливалась, чтобы обдумать это, и нам еще предстоит придумать лучший вариант.
Извините, я, должно быть, недооценил это. Почему бы не найти объекты в словаре, а затем создать полную копию объекта (например, IDeepCopyable
) или использовать отражение для выполнения этой работы?
Примерно:
public interface IDeepCopyable {
object DeepCopy();
}
public class Cache<TKey, TValue> where TValue : IDeepCopyable {
Dictionary<TKey, TValue> dictionary = new Dictionary<TKey, TValue>();
// omit dictionary-manipulation code
public TValue this[TKey key] {
get {
return dictionary[key].DeepCopy(); // could use reflection to clone too
}
}
}
Если вы пойдете по пути отражения, у Марка Гравелла есть хороший код клонирования , который легко изменить для создания глубокой копии.
Вот простая функция, которая будет использовать отражение для глубокого копирования и объекта, независимо от типа. Я взял это отчасти из гораздо более сложной процедуры копирования, которую я использовал в старые времена веб-сервисов для копирования между почти идентичными (tm) типами данных. Это может работать не совсем точно, но это дает вам общее представление. Это очень упрощенно, и при использовании необработанного отражения существует много граничных случаев ...
public static object ObjCopy(object inObj)
{
if( inObj == null ) return null;
System.Type type = inObj.GetType();
if(type.IsValueType)
{
return inObj;
}
else if(type.IsClass)
{
object outObj = Activator.CreateInstance(type);
System.Type fieldType;
foreach(FieldInfo fi in type.GetFields())
{
fieldType = fi.GetType();
if(fieldType.IsValueType) //Value types get copied
{
fi.SetValue(outObj, fi.GetValue(inObj));
}
else if(fieldType.IsClass) //Classes go deeper
{
//Recursion
fi.SetValue(outObj, ObjCopy(fi.GetValue(inObj)));
}
}
return outObj;
}
else
{
return null;
}
}
Лично я бы использовал процедуры сериализатора, поскольку они автоматически обрабатывают все граничные случаи. По умолчанию, по крайней мере в .NET 2.0, система динамически создает сборку сериализации. Вы можете ускорить сериализацию, кэшируя сериализаторы. Этот пример кода из моего приложения кэширует XmlSerializers.
protected static XmlSerializer SerializerGet(System.Type type)
{
XmlSerializer output = null;
lock(typeof(SerializeAssist))
{
if(serializerList.ContainsKey(type))
{
output = serializerList[type];
}
else
{
if(type == typeof(object) || type == typeof(object[]) || type == typeof(ArrayList))
{
output = new XmlSerializer(type, objArrayTypes);
}
else
{
output = new XmlSerializer(type);
}
serializerList.Add(type, output);
}
}
return output;
}